blob: ecd4c9f3af83d3eeb7ff1d01a99c7f50ad0278f2 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreauff011f22011-01-06 17:51:27 +01004 * Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
Cyril Bonté1a0191d2014-08-29 20:20:02 +020013#ifdef CONFIG_HAP_CRYPT
14/* This is to have crypt() defined on Linux */
15#define _GNU_SOURCE
16
17#ifdef NEED_CRYPT_H
18/* some platforms such as Solaris need this */
19#include <crypt.h>
20#endif
21#endif /* CONFIG_HAP_CRYPT */
22
Willy Tarreaubaaee002006-06-26 02:48:02 +020023#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <netdb.h>
27#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020028#include <pwd.h>
29#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020030#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020031#include <sys/types.h>
32#include <sys/stat.h>
33#include <fcntl.h>
34#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
Willy Tarreau2dd0d472006-06-29 17:53:05 +020036#include <common/cfgparse.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020037#include <common/chunk.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020038#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020039#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020040#include <common/memory.h>
41#include <common/standard.h>
42#include <common/time.h>
43#include <common/uri_auth.h>
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +010044#include <common/namespace.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020045
46#include <types/capture.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020047#include <types/compression.h>
Christopher Fauletd7c91962015-04-30 11:48:27 +020048#include <types/filters.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020049#include <types/global.h>
Willy Tarreau3fdb3662012-11-12 00:42:33 +010050#include <types/obj_type.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020051#include <types/peers.h>
Simon Horman0d16a402015-01-30 11:22:58 +090052#include <types/mailers.h>
Baptiste Assmann325137d2015-04-13 23:40:55 +020053#include <types/dns.h>
William Lallemand9ed62032016-11-21 17:49:11 +010054#include <types/stats.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020055
Willy Tarreaueb0c6142007-05-07 00:53:22 +020056#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010057#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020058#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020059#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020060#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020061#include <proto/compression.h>
Baptiste Assmann201c07f2017-05-22 15:17:15 +020062#include <proto/dns.h>
William Lallemand9ed62032016-11-21 17:49:11 +010063#include <proto/stats.h>
Christopher Fauletd7c91962015-04-30 11:48:27 +020064#include <proto/filters.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020065#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020066#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020067#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010068#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020069#include <proto/lb_fwlc.h>
70#include <proto/lb_fwrr.h>
71#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020072#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020073#include <proto/log.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020074#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010075#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020076#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010077#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010078#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020079#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020080#include <proto/sample.h>
Willy Tarreau9903f0e2015-04-04 18:50:31 +020081#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020082#include <proto/server.h>
Willy Tarreau87b09662015-04-03 00:22:06 +020083#include <proto/stream.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010084#include <proto/stick_table.h>
Willy Tarreau39713102016-11-25 15:49:32 +010085#include <proto/task.h>
86#include <proto/tcp_rules.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020087
88
Willy Tarreauf3c69202006-07-09 16:42:34 +020089/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
90 * ssl-hello-chk option to ensure that the remote server speaks SSL.
91 *
92 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
93 */
94const char sslv3_client_hello_pkt[] = {
95 "\x16" /* ContentType : 0x16 = Hanshake */
96 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
97 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
98 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
99 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
100 "\x03\x00" /* Hello Version : 0x0300 = v3 */
101 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
102 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
103 "\x00" /* Session ID length : empty (no session ID) */
104 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
105 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
106 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
107 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
108 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
109 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
110 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
111 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
112 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
113 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
114 "\x00\x38" "\x00\x39" "\x00\x3A"
115 "\x01" /* Compression Length : 0x01 = 1 byte for types */
116 "\x00" /* Compression Type : 0x00 = NULL compression */
117};
118
Willy Tarreau3842f002009-06-14 11:39:52 +0200119/* various keyword modifiers */
120enum kw_mod {
121 KWM_STD = 0, /* normal */
122 KWM_NO, /* "no" prefixed before the keyword */
123 KWM_DEF, /* "default" prefixed before the keyword */
124};
125
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +0100126/* permit to store configuration section */
127struct cfg_section {
128 struct list list;
129 char *section_name;
130 int (*section_parser)(const char *, int, char **, int);
131};
132
133/* Used to chain configuration sections definitions. This list
134 * stores struct cfg_section
135 */
136struct list sections = LIST_HEAD_INIT(sections);
137
Willy Tarreau13943ab2006-12-31 00:24:10 +0100138/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100139struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100140 const char *name;
141 unsigned int val;
142 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100143 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100144 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100145};
146
147/* proxy->options */
148static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100149{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100150 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
151 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
152 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
153 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
154 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
155 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100156 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau9fbe18e2015-05-01 22:42:08 +0200157 { "http-buffer-request", PR_O_WREQ_BODY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau0f228a02015-05-01 15:37:53 +0200158 { "http-ignore-probes", PR_O_IGNORE_PRB, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreau9420b122013-12-15 18:58:25 +0100159 { "prefer-last-server", PR_O_PREF_LAST, PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100160 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
161 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
162 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100163 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100164#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100165 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100166#else
167 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100168#endif
169
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100170 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100171};
172
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100173/* proxy->options2 */
174static const struct cfg_opt cfg_opts2[] =
175{
176#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100177 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
178 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
179 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100180#else
181 { "splice-request", 0, 0, 0, 0 },
182 { "splice-response", 0, 0, 0, 0 },
183 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100184#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100185 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
186 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
187 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
188 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
189 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
190 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
191 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
192 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
193 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400194 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100195 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200196 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200197 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100198 { NULL, 0, 0, 0 }
199};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200200
Willy Tarreau6daf3432008-01-22 16:44:08 +0100201static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200202static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
203int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100204int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Christopher Faulet79bdef32016-11-04 22:36:15 +0100205char *cfg_scope = NULL; /* the current scope during the configuration parsing */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200206
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200207/* List head of all known configuration keywords */
208static struct cfg_kw_list cfg_keywords = {
209 .list = LIST_HEAD_INIT(cfg_keywords.list)
210};
211
Willy Tarreaubaaee002006-06-26 02:48:02 +0200212/*
213 * converts <str> to a list of listeners which are dynamically allocated.
214 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
215 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
216 * - <port> is a numerical port from 1 to 65535 ;
217 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
218 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200219 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
220 * not NULL, it must be a valid pointer to either NULL or a freeable area that
221 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200222 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200223int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf, const char *file, int line, char **err)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200224{
225 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100226 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200227 int port, end;
228
229 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200230
Willy Tarreaubaaee002006-06-26 02:48:02 +0200231 while (next && *next) {
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100232 struct sockaddr_storage ss, *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100233 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200234
235 str = next;
236 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100237 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200238 *next++ = 0;
239 }
240
Willy Tarreau48ef4c92017-01-06 18:32:38 +0100241 ss2 = str2sa_range(str, NULL, &port, &end, err,
Willy Tarreau72b8c1f2015-09-08 15:50:19 +0200242 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix,
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +0200243 NULL, 1);
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100244 if (!ss2)
245 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200246
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100247 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100248 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200249 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100250 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200251 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200252
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100253 if (!port || !end) {
254 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
255 goto fail;
256 }
257
Emeric Bruned760922010-10-22 17:59:25 +0200258 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200259 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200260 goto fail;
261 }
262
263 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200264 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200265 goto fail;
266 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200267 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100268 else if (ss2->ss_family == AF_UNSPEC) {
269 socklen_t addr_len;
270
271 /* We want to attach to an already bound fd whose number
272 * is in the addr part of ss2 when cast to sockaddr_in.
273 * Note that by definition there is a single listener.
274 * We still have to determine the address family to
275 * register the correct protocol.
276 */
277 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
278 addr_len = sizeof(*ss2);
279 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
280 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
281 goto fail;
282 }
283
284 port = end = get_host_port(ss2);
285 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200286
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100287 /* OK the address looks correct */
Vincent Bernat6e615892016-05-18 16:17:44 +0200288 memcpy(&ss, ss2, sizeof(ss));
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100289
Willy Tarreaubaaee002006-06-26 02:48:02 +0200290 for (; port <= end; port++) {
Vincent Bernat02779b62016-04-03 13:48:43 +0200291 l = calloc(1, sizeof(*l));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100292 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200293 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
294 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
Willy Tarreau4348fad2012-09-20 16:48:07 +0200295 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200296
Willy Tarreau40aa0702013-03-10 23:51:38 +0100297 l->fd = fd;
Vincent Bernat6e46ff12016-05-19 11:29:43 +0200298 memcpy(&l->addr, &ss, sizeof(ss));
Willy Tarreaue6b98942007-10-29 01:09:36 +0100299 l->state = LI_INIT;
300
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100301 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200302 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100303 tcpv4_add_listener(l);
304 }
Emeric Bruned760922010-10-22 17:59:25 +0200305 else if (ss.ss_family == AF_INET6) {
306 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
307 tcpv6_add_listener(l);
308 }
309 else {
Emeric Bruned760922010-10-22 17:59:25 +0200310 uxst_add_listener(l);
311 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200312
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200313 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100314 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200315 } /* end for(port) */
316 } /* end while(next) */
317 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200318 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200319 fail:
320 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200321 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200322}
323
William Lallemand6e62fb62015-04-28 16:55:23 +0200324/*
Willy Tarreauece9b072016-12-21 22:41:44 +0100325 * Report an error in <msg> when there are too many arguments. This version is
326 * intended to be used by keyword parsers so that the message will be included
327 * into the general error message. The index is the current keyword in args.
328 * Return 0 if the number of argument is correct, otherwise build a message and
329 * return 1. Fill err_code with an ERR_ALERT and an ERR_FATAL if not null. The
330 * message may also be null, it will simply not be produced (useful to check only).
331 * <msg> and <err_code> are only affected on error.
332 */
333int too_many_args_idx(int maxarg, int index, char **args, char **msg, int *err_code)
334{
335 int i;
336
337 if (!*args[index + maxarg + 1])
338 return 0;
339
340 if (msg) {
341 *msg = NULL;
342 memprintf(msg, "%s", args[0]);
343 for (i = 1; i <= index; i++)
344 memprintf(msg, "%s %s", *msg, args[i]);
345
346 memprintf(msg, "'%s' cannot handle unexpected argument '%s'.", *msg, args[index + maxarg + 1]);
347 }
348 if (err_code)
349 *err_code |= ERR_ALERT | ERR_FATAL;
350
351 return 1;
352}
353
354/*
355 * same as too_many_args_idx with a 0 index
356 */
357int too_many_args(int maxarg, char **args, char **msg, int *err_code)
358{
359 return too_many_args_idx(maxarg, 0, args, msg, err_code);
360}
361
362/*
William Lallemand6e62fb62015-04-28 16:55:23 +0200363 * Report a fatal Alert when there is too much arguments
364 * The index is the current keyword in args
365 * Return 0 if the number of argument is correct, otherwise emit an alert and return 1
366 * Fill err_code with an ERR_ALERT and an ERR_FATAL
367 */
368int alertif_too_many_args_idx(int maxarg, int index, const char *file, int linenum, char **args, int *err_code)
369{
370 char *kw = NULL;
371 int i;
372
373 if (!*args[index + maxarg + 1])
374 return 0;
375
376 memprintf(&kw, "%s", args[0]);
377 for (i = 1; i <= index; i++) {
378 memprintf(&kw, "%s %s", kw, args[i]);
379 }
380
381 Alert("parsing [%s:%d] : '%s' cannot handle unexpected argument '%s'.\n", file, linenum, kw, args[index + maxarg + 1]);
382 free(kw);
383 *err_code |= ERR_ALERT | ERR_FATAL;
384 return 1;
385}
386
387/*
388 * same as alertif_too_many_args_idx with a 0 index
389 */
390int alertif_too_many_args(int maxarg, const char *file, int linenum, char **args, int *err_code)
391{
392 return alertif_too_many_args_idx(maxarg, 0, file, linenum, args, err_code);
393}
394
Willy Tarreau620408f2016-10-21 16:37:51 +0200395/* Report a warning if a rule is placed after a 'tcp-request session' rule.
396 * Return 1 if the warning has been emitted, otherwise 0.
397 */
398int warnif_rule_after_tcp_sess(struct proxy *proxy, const char *file, int line, const char *arg)
399{
400 if (!LIST_ISEMPTY(&proxy->tcp_req.l5_rules)) {
401 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request session' rule will still be processed before.\n",
402 file, line, arg);
403 return 1;
404 }
405 return 0;
406}
407
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200408/* Report a warning if a rule is placed after a 'tcp-request content' rule.
409 * Return 1 if the warning has been emitted, otherwise 0.
410 */
411int warnif_rule_after_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
412{
413 if (!LIST_ISEMPTY(&proxy->tcp_req.inspect_rules)) {
414 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request content' rule will still be processed before.\n",
415 file, line, arg);
416 return 1;
417 }
418 return 0;
419}
420
Willy Tarreau61d18892009-03-31 10:49:21 +0200421/* Report a warning if a rule is placed after a 'block' rule.
422 * Return 1 if the warning has been emitted, otherwise 0.
423 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100424int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200425{
Willy Tarreau353bc9f2014-04-28 22:05:31 +0200426 if (!LIST_ISEMPTY(&proxy->block_rules)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200427 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
428 file, line, arg);
429 return 1;
430 }
431 return 0;
432}
433
Willy Tarreau5002f572014-04-23 01:32:02 +0200434/* Report a warning if a rule is placed after an 'http_request' rule.
435 * Return 1 if the warning has been emitted, otherwise 0.
436 */
437int warnif_rule_after_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
438{
439 if (!LIST_ISEMPTY(&proxy->http_req_rules)) {
440 Warning("parsing [%s:%d] : a '%s' rule placed after an 'http-request' rule will still be processed before.\n",
441 file, line, arg);
442 return 1;
443 }
444 return 0;
445}
446
Willy Tarreau61d18892009-03-31 10:49:21 +0200447/* Report a warning if a rule is placed after a reqrewrite rule.
448 * Return 1 if the warning has been emitted, otherwise 0.
449 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100450int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200451{
452 if (proxy->req_exp) {
453 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
454 file, line, arg);
455 return 1;
456 }
457 return 0;
458}
459
460/* Report a warning if a rule is placed after a reqadd rule.
461 * Return 1 if the warning has been emitted, otherwise 0.
462 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100463int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200464{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100465 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200466 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
467 file, line, arg);
468 return 1;
469 }
470 return 0;
471}
472
473/* Report a warning if a rule is placed after a redirect rule.
474 * Return 1 if the warning has been emitted, otherwise 0.
475 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100476int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200477{
478 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
479 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
480 file, line, arg);
481 return 1;
482 }
483 return 0;
484}
485
486/* Report a warning if a rule is placed after a 'use_backend' rule.
487 * Return 1 if the warning has been emitted, otherwise 0.
488 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100489int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200490{
491 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
492 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
493 file, line, arg);
494 return 1;
495 }
496 return 0;
497}
498
Willy Tarreauee445d92014-04-23 01:39:04 +0200499/* Report a warning if a rule is placed after a 'use-server' rule.
500 * Return 1 if the warning has been emitted, otherwise 0.
501 */
502int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line, const char *arg)
503{
504 if (!LIST_ISEMPTY(&proxy->server_rules)) {
505 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use-server' rule will still be processed before.\n",
506 file, line, arg);
507 return 1;
508 }
509 return 0;
510}
511
Willy Tarreaud39ad442016-11-25 15:16:12 +0100512/* report a warning if a redirect rule is dangerously placed */
513int warnif_misplaced_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau620408f2016-10-21 16:37:51 +0200514{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100515 return warnif_rule_after_use_backend(proxy, file, line, arg) ||
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200516 warnif_rule_after_use_server(proxy, file, line, arg);
517}
518
Willy Tarreaud39ad442016-11-25 15:16:12 +0100519/* report a warning if a reqadd rule is dangerously placed */
520int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200521{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100522 return warnif_rule_after_redirect(proxy, file, line, arg) ||
523 warnif_misplaced_redirect(proxy, file, line, arg);
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200524}
525
Willy Tarreaud39ad442016-11-25 15:16:12 +0100526/* report a warning if a reqxxx rule is dangerously placed */
527int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200528{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100529 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
530 warnif_misplaced_reqadd(proxy, file, line, arg);
Willy Tarreau5002f572014-04-23 01:32:02 +0200531}
532
533/* report a warning if an http-request rule is dangerously placed */
534int warnif_misplaced_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
535{
Willy Tarreau61d18892009-03-31 10:49:21 +0200536 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
Willy Tarreaud39ad442016-11-25 15:16:12 +0100537 warnif_misplaced_reqxxx(proxy, file, line, arg);;
Willy Tarreau61d18892009-03-31 10:49:21 +0200538}
539
Willy Tarreaud39ad442016-11-25 15:16:12 +0100540/* report a warning if a block rule is dangerously placed */
541int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200542{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100543 return warnif_rule_after_http_req(proxy, file, line, arg) ||
544 warnif_misplaced_http_req(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200545}
546
Willy Tarreaud39ad442016-11-25 15:16:12 +0100547/* report a warning if a "tcp request content" rule is dangerously placed */
548int warnif_misplaced_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200549{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100550 return warnif_rule_after_block(proxy, file, line, arg) ||
551 warnif_misplaced_block(proxy, file, line, arg);
Willy Tarreauee445d92014-04-23 01:39:04 +0200552}
553
Willy Tarreaud39ad442016-11-25 15:16:12 +0100554/* report a warning if a "tcp request session" rule is dangerously placed */
555int warnif_misplaced_tcp_sess(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreauee445d92014-04-23 01:39:04 +0200556{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100557 return warnif_rule_after_tcp_cont(proxy, file, line, arg) ||
558 warnif_misplaced_tcp_cont(proxy, file, line, arg);
559}
560
561/* report a warning if a "tcp request connection" rule is dangerously placed */
562int warnif_misplaced_tcp_conn(struct proxy *proxy, const char *file, int line, const char *arg)
563{
564 return warnif_rule_after_tcp_sess(proxy, file, line, arg) ||
565 warnif_misplaced_tcp_sess(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200566}
567
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100568/* Report it if a request ACL condition uses some keywords that are incompatible
569 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
570 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
571 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100572 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100573static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100574{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100575 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200576 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100577
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100578 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100579 return 0;
580
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100581 acl = acl_cond_conflicts(cond, where);
582 if (acl) {
583 if (acl->name && *acl->name)
584 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
585 file, line, acl->name, sample_ckp_names(where));
586 else
587 Warning("parsing [%s:%d] : anonymous acl will never match because it uses keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200588 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100589 return ERR_WARN;
590 }
591 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100592 return 0;
593
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100594 if (acl->name && *acl->name)
595 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200596 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100597 else
598 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200599 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100600 return ERR_WARN;
601}
602
Willy Tarreaubaaee002006-06-26 02:48:02 +0200603/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200604 * parse a line in a <global> section. Returns the error code, 0 if OK, or
605 * any combination of :
606 * - ERR_ABORT: must abort ASAP
607 * - ERR_FATAL: we can continue parsing but not start the service
608 * - ERR_WARN: a warning has been emitted
609 * - ERR_ALERT: an alert has been emitted
610 * Only the two first ones can stop processing, the two others are just
611 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200612 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200613int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200614{
Willy Tarreau058e9072009-07-20 09:30:05 +0200615 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200616 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200617
618 if (!strcmp(args[0], "global")) { /* new section */
619 /* no option, nothing special to do */
William Lallemand6e62fb62015-04-28 16:55:23 +0200620 alertif_too_many_args(0, file, linenum, args, &err_code);
Willy Tarreau058e9072009-07-20 09:30:05 +0200621 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200622 }
623 else if (!strcmp(args[0], "daemon")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200624 if (alertif_too_many_args(0, file, linenum, args, &err_code))
625 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200626 global.mode |= MODE_DAEMON;
627 }
William Lallemand095ba4c2017-06-01 17:38:50 +0200628 else if (!strcmp(args[0], "master-worker")) {
William Lallemand69f9b3b2017-06-01 17:38:54 +0200629 if (alertif_too_many_args(1, file, linenum, args, &err_code))
William Lallemand095ba4c2017-06-01 17:38:50 +0200630 goto out;
William Lallemand69f9b3b2017-06-01 17:38:54 +0200631 if (*args[1]) {
632 if (!strcmp(args[1], "exit-on-failure")) {
633 global.tune.options |= GTUNE_EXIT_ONFAILURE;
634 } else {
635 Alert("parsing [%s:%d] : '%s' only supports 'exit-on-failure' option.\n", file, linenum, args[0]);
636 err_code |= ERR_ALERT | ERR_FATAL;
637 goto out;
638 }
639 }
William Lallemand095ba4c2017-06-01 17:38:50 +0200640 global.mode |= MODE_MWORKER;
641 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200642 else if (!strcmp(args[0], "debug")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200643 if (alertif_too_many_args(0, file, linenum, args, &err_code))
644 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200645 global.mode |= MODE_DEBUG;
646 }
647 else if (!strcmp(args[0], "noepoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200648 if (alertif_too_many_args(0, file, linenum, args, &err_code))
649 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100650 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200651 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200652 else if (!strcmp(args[0], "nokqueue")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200653 if (alertif_too_many_args(0, file, linenum, args, &err_code))
654 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100655 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200656 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200657 else if (!strcmp(args[0], "nopoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200658 if (alertif_too_many_args(0, file, linenum, args, &err_code))
659 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100660 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200661 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100662 else if (!strcmp(args[0], "nosplice")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200663 if (alertif_too_many_args(0, file, linenum, args, &err_code))
664 goto out;
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100665 global.tune.options &= ~GTUNE_USE_SPLICE;
666 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200667 else if (!strcmp(args[0], "nogetaddrinfo")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200668 if (alertif_too_many_args(0, file, linenum, args, &err_code))
669 goto out;
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200670 global.tune.options &= ~GTUNE_USE_GAI;
671 }
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +0000672 else if (!strcmp(args[0], "noreuseport")) {
673 if (alertif_too_many_args(0, file, linenum, args, &err_code))
674 goto out;
675 global.tune.options &= ~GTUNE_USE_REUSEPORT;
676 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200677 else if (!strcmp(args[0], "quiet")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200678 if (alertif_too_many_args(0, file, linenum, args, &err_code))
679 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200680 global.mode |= MODE_QUIET;
681 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200682 else if (!strcmp(args[0], "tune.maxpollevents")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200683 if (alertif_too_many_args(1, file, linenum, args, &err_code))
684 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200685 if (global.tune.maxpollevents != 0) {
686 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200687 err_code |= ERR_ALERT;
688 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200689 }
690 if (*(args[1]) == 0) {
691 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200692 err_code |= ERR_ALERT | ERR_FATAL;
693 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200694 }
695 global.tune.maxpollevents = atol(args[1]);
696 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100697 else if (!strcmp(args[0], "tune.maxaccept")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200698 if (alertif_too_many_args(1, file, linenum, args, &err_code))
699 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100700 if (global.tune.maxaccept != 0) {
701 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200702 err_code |= ERR_ALERT;
703 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100704 }
705 if (*(args[1]) == 0) {
706 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200707 err_code |= ERR_ALERT | ERR_FATAL;
708 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100709 }
710 global.tune.maxaccept = atol(args[1]);
711 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200712 else if (!strcmp(args[0], "tune.chksize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200713 if (alertif_too_many_args(1, file, linenum, args, &err_code))
714 goto out;
Willy Tarreau43961d52010-10-04 20:39:20 +0200715 if (*(args[1]) == 0) {
716 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
717 err_code |= ERR_ALERT | ERR_FATAL;
718 goto out;
719 }
720 global.tune.chksize = atol(args[1]);
721 }
Willy Tarreaub22fc302015-12-14 12:04:35 +0100722 else if (!strcmp(args[0], "tune.recv_enough")) {
723 if (alertif_too_many_args(1, file, linenum, args, &err_code))
724 goto out;
725 if (*(args[1]) == 0) {
726 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
727 err_code |= ERR_ALERT | ERR_FATAL;
728 goto out;
729 }
730 global.tune.recv_enough = atol(args[1]);
731 }
Willy Tarreau33cb0652014-12-23 22:52:37 +0100732 else if (!strcmp(args[0], "tune.buffers.limit")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200733 if (alertif_too_many_args(1, file, linenum, args, &err_code))
734 goto out;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100735 if (*(args[1]) == 0) {
736 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
737 err_code |= ERR_ALERT | ERR_FATAL;
738 goto out;
739 }
740 global.tune.buf_limit = atol(args[1]);
741 if (global.tune.buf_limit) {
742 if (global.tune.buf_limit < 3)
743 global.tune.buf_limit = 3;
744 if (global.tune.buf_limit <= global.tune.reserved_bufs)
745 global.tune.buf_limit = global.tune.reserved_bufs + 1;
746 }
747 }
Willy Tarreau1058ae72014-12-23 22:40:40 +0100748 else if (!strcmp(args[0], "tune.buffers.reserve")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200749 if (alertif_too_many_args(1, file, linenum, args, &err_code))
750 goto out;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100751 if (*(args[1]) == 0) {
752 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
753 err_code |= ERR_ALERT | ERR_FATAL;
754 goto out;
755 }
756 global.tune.reserved_bufs = atol(args[1]);
757 if (global.tune.reserved_bufs < 2)
758 global.tune.reserved_bufs = 2;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100759 if (global.tune.buf_limit && global.tune.buf_limit <= global.tune.reserved_bufs)
760 global.tune.buf_limit = global.tune.reserved_bufs + 1;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100761 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200762 else if (!strcmp(args[0], "tune.bufsize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200763 if (alertif_too_many_args(1, file, linenum, args, &err_code))
764 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200765 if (*(args[1]) == 0) {
766 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
767 err_code |= ERR_ALERT | ERR_FATAL;
768 goto out;
769 }
770 global.tune.bufsize = atol(args[1]);
Willy Tarreau9b694542015-09-28 13:49:53 +0200771 if (global.tune.bufsize <= 0) {
772 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
773 err_code |= ERR_ALERT | ERR_FATAL;
774 goto out;
775 }
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100776 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100777 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200778 }
779 else if (!strcmp(args[0], "tune.maxrewrite")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200780 if (alertif_too_many_args(1, file, linenum, args, &err_code))
781 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200782 if (*(args[1]) == 0) {
783 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
784 err_code |= ERR_ALERT | ERR_FATAL;
785 goto out;
786 }
787 global.tune.maxrewrite = atol(args[1]);
Willy Tarreau27097842015-09-28 13:53:23 +0200788 if (global.tune.maxrewrite < 0) {
789 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
790 err_code |= ERR_ALERT | ERR_FATAL;
791 goto out;
792 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200793 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100794 else if (!strcmp(args[0], "tune.idletimer")) {
795 unsigned int idle;
796 const char *res;
797
William Lallemand1a748ae2015-05-19 16:37:23 +0200798 if (alertif_too_many_args(1, file, linenum, args, &err_code))
799 goto out;
Willy Tarreau7e312732014-02-12 16:35:14 +0100800 if (*(args[1]) == 0) {
801 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
802 err_code |= ERR_ALERT | ERR_FATAL;
803 goto out;
804 }
805
806 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
807 if (res) {
808 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
809 file, linenum, *res, args[0]);
810 err_code |= ERR_ALERT | ERR_FATAL;
811 goto out;
812 }
813
814 if (idle > 65535) {
815 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
816 err_code |= ERR_ALERT | ERR_FATAL;
817 goto out;
818 }
819 global.tune.idle_timer = idle;
820 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100821 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200822 if (alertif_too_many_args(1, file, linenum, args, &err_code))
823 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100824 if (global.tune.client_rcvbuf != 0) {
825 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
826 err_code |= ERR_ALERT;
827 goto out;
828 }
829 if (*(args[1]) == 0) {
830 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
831 err_code |= ERR_ALERT | ERR_FATAL;
832 goto out;
833 }
834 global.tune.client_rcvbuf = atol(args[1]);
835 }
836 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200837 if (alertif_too_many_args(1, file, linenum, args, &err_code))
838 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100839 if (global.tune.server_rcvbuf != 0) {
840 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
841 err_code |= ERR_ALERT;
842 goto out;
843 }
844 if (*(args[1]) == 0) {
845 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
846 err_code |= ERR_ALERT | ERR_FATAL;
847 goto out;
848 }
849 global.tune.server_rcvbuf = atol(args[1]);
850 }
851 else if (!strcmp(args[0], "tune.sndbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200852 if (alertif_too_many_args(1, file, linenum, args, &err_code))
853 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100854 if (global.tune.client_sndbuf != 0) {
855 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
856 err_code |= ERR_ALERT;
857 goto out;
858 }
859 if (*(args[1]) == 0) {
860 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
861 err_code |= ERR_ALERT | ERR_FATAL;
862 goto out;
863 }
864 global.tune.client_sndbuf = atol(args[1]);
865 }
866 else if (!strcmp(args[0], "tune.sndbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200867 if (alertif_too_many_args(1, file, linenum, args, &err_code))
868 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100869 if (global.tune.server_sndbuf != 0) {
870 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
871 err_code |= ERR_ALERT;
872 goto out;
873 }
874 if (*(args[1]) == 0) {
875 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
876 err_code |= ERR_ALERT | ERR_FATAL;
877 goto out;
878 }
879 global.tune.server_sndbuf = atol(args[1]);
880 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200881 else if (!strcmp(args[0], "tune.pipesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200882 if (alertif_too_many_args(1, file, linenum, args, &err_code))
883 goto out;
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200884 if (*(args[1]) == 0) {
885 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
886 err_code |= ERR_ALERT | ERR_FATAL;
887 goto out;
888 }
889 global.tune.pipesize = atol(args[1]);
890 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100891 else if (!strcmp(args[0], "tune.http.cookielen")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200892 if (alertif_too_many_args(1, file, linenum, args, &err_code))
893 goto out;
Willy Tarreau193b8c62012-11-22 00:17:38 +0100894 if (*(args[1]) == 0) {
895 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
896 err_code |= ERR_ALERT | ERR_FATAL;
897 goto out;
898 }
899 global.tune.cookie_len = atol(args[1]) + 1;
900 }
Stéphane Cottin23e9e932017-05-18 08:58:41 +0200901 else if (!strcmp(args[0], "tune.http.logurilen")) {
902 if (alertif_too_many_args(1, file, linenum, args, &err_code))
903 goto out;
904 if (*(args[1]) == 0) {
905 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
906 err_code |= ERR_ALERT | ERR_FATAL;
907 goto out;
908 }
909 global.tune.requri_len = atol(args[1]) + 1;
910 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200911 else if (!strcmp(args[0], "tune.http.maxhdr")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200912 if (alertif_too_many_args(1, file, linenum, args, &err_code))
913 goto out;
Willy Tarreauac1932d2011-10-24 19:14:41 +0200914 if (*(args[1]) == 0) {
915 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
916 err_code |= ERR_ALERT | ERR_FATAL;
917 goto out;
918 }
Christopher Faulet50174f32017-06-21 16:31:35 +0200919 global.tune.max_http_hdr = atoi(args[1]);
920 if (global.tune.max_http_hdr < 1 || global.tune.max_http_hdr > 32767) {
921 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 32767\n",
922 file, linenum, args[0]);
923 err_code |= ERR_ALERT | ERR_FATAL;
924 goto out;
925 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200926 }
William Lallemandf3747832012-11-09 12:33:10 +0100927 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200928 if (alertif_too_many_args(1, file, linenum, args, &err_code))
929 goto out;
William Lallemandf3747832012-11-09 12:33:10 +0100930 if (*args[1]) {
931 global.tune.comp_maxlevel = atoi(args[1]);
932 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
933 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
934 file, linenum, args[0]);
935 err_code |= ERR_ALERT | ERR_FATAL;
936 goto out;
937 }
938 } else {
939 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
940 file, linenum, args[0]);
941 err_code |= ERR_ALERT | ERR_FATAL;
942 goto out;
943 }
944 }
Willy Tarreauf3045d22015-04-29 16:24:50 +0200945 else if (!strcmp(args[0], "tune.pattern.cache-size")) {
946 if (*args[1]) {
947 global.tune.pattern_cache = atoi(args[1]);
948 if (global.tune.pattern_cache < 0) {
949 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
950 file, linenum, args[0]);
951 err_code |= ERR_ALERT | ERR_FATAL;
952 goto out;
953 }
954 } else {
955 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
956 file, linenum, args[0]);
957 err_code |= ERR_ALERT | ERR_FATAL;
958 goto out;
959 }
960 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200961 else if (!strcmp(args[0], "uid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200962 if (alertif_too_many_args(1, file, linenum, args, &err_code))
963 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200964 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200965 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200966 err_code |= ERR_ALERT;
967 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200968 }
969 if (*(args[1]) == 0) {
970 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200971 err_code |= ERR_ALERT | ERR_FATAL;
972 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200973 }
Baptiste Assmann79fee6a2016-03-11 17:10:04 +0100974 if (strl2irc(args[1], strlen(args[1]), &global.uid) != 0) {
975 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]);
976 err_code |= ERR_WARN;
977 goto out;
978 }
979
Willy Tarreaubaaee002006-06-26 02:48:02 +0200980 }
981 else if (!strcmp(args[0], "gid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200982 if (alertif_too_many_args(1, file, linenum, args, &err_code))
983 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200984 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200985 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200986 err_code |= ERR_ALERT;
987 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200988 }
989 if (*(args[1]) == 0) {
990 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200991 err_code |= ERR_ALERT | ERR_FATAL;
992 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200993 }
Baptiste Assmann776e5182016-03-11 17:21:15 +0100994 if (strl2irc(args[1], strlen(args[1]), &global.gid) != 0) {
995 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]);
996 err_code |= ERR_WARN;
997 goto out;
998 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200999 }
Simon Horman98637e52014-06-20 12:30:16 +09001000 else if (!strcmp(args[0], "external-check")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001001 if (alertif_too_many_args(0, file, linenum, args, &err_code))
1002 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09001003 global.external_check = 1;
1004 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001005 /* user/group name handling */
1006 else if (!strcmp(args[0], "user")) {
1007 struct passwd *ha_user;
William Lallemand1a748ae2015-05-19 16:37:23 +02001008 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1009 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001010 if (global.uid != 0) {
1011 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001012 err_code |= ERR_ALERT;
1013 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001014 }
1015 errno = 0;
1016 ha_user = getpwnam(args[1]);
1017 if (ha_user != NULL) {
1018 global.uid = (int)ha_user->pw_uid;
1019 }
1020 else {
1021 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +02001022 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001023 }
1024 }
1025 else if (!strcmp(args[0], "group")) {
1026 struct group *ha_group;
William Lallemand1a748ae2015-05-19 16:37:23 +02001027 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1028 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001029 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02001030 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001031 err_code |= ERR_ALERT;
1032 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001033 }
1034 errno = 0;
1035 ha_group = getgrnam(args[1]);
1036 if (ha_group != NULL) {
1037 global.gid = (int)ha_group->gr_gid;
1038 }
1039 else {
1040 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +02001041 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001042 }
1043 }
1044 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +02001045 else if (!strcmp(args[0], "nbproc")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001046 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1047 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001048 if (*(args[1]) == 0) {
1049 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001050 err_code |= ERR_ALERT | ERR_FATAL;
1051 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001052 }
1053 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001054 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
1055 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
1056 file, linenum, args[0], LONGBITS, global.nbproc);
1057 err_code |= ERR_ALERT | ERR_FATAL;
1058 goto out;
1059 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001060 }
1061 else if (!strcmp(args[0], "maxconn")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001062 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1063 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001064 if (global.maxconn != 0) {
1065 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001066 err_code |= ERR_ALERT;
1067 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001068 }
1069 if (*(args[1]) == 0) {
1070 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001071 err_code |= ERR_ALERT | ERR_FATAL;
1072 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001073 }
1074 global.maxconn = atol(args[1]);
1075#ifdef SYSTEM_MAXCONN
1076 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
1077 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);
1078 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +02001079 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001080 }
1081#endif /* SYSTEM_MAXCONN */
1082 }
Emeric Brun850efd52014-01-29 12:24:34 +01001083 else if (!strcmp(args[0], "ssl-server-verify")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001084 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1085 goto out;
Emeric Brun850efd52014-01-29 12:24:34 +01001086 if (*(args[1]) == 0) {
1087 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1088 err_code |= ERR_ALERT | ERR_FATAL;
1089 goto out;
1090 }
1091 if (strcmp(args[1],"none") == 0)
1092 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1093 else if (strcmp(args[1],"required") == 0)
1094 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1095 else {
1096 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1097 err_code |= ERR_ALERT | ERR_FATAL;
1098 goto out;
1099 }
1100 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001101 else if (!strcmp(args[0], "maxconnrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001102 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1103 goto out;
Willy Tarreau81c25d02011-09-07 15:17:21 +02001104 if (global.cps_lim != 0) {
1105 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1106 err_code |= ERR_ALERT;
1107 goto out;
1108 }
1109 if (*(args[1]) == 0) {
1110 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1111 err_code |= ERR_ALERT | ERR_FATAL;
1112 goto out;
1113 }
1114 global.cps_lim = atol(args[1]);
1115 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001116 else if (!strcmp(args[0], "maxsessrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001117 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1118 goto out;
Willy Tarreau93e7c002013-10-07 18:51:07 +02001119 if (global.sps_lim != 0) {
1120 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1121 err_code |= ERR_ALERT;
1122 goto out;
1123 }
1124 if (*(args[1]) == 0) {
1125 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1126 err_code |= ERR_ALERT | ERR_FATAL;
1127 goto out;
1128 }
1129 global.sps_lim = atol(args[1]);
1130 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001131 else if (!strcmp(args[0], "maxsslrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001132 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1133 goto out;
Willy Tarreaue43d5322013-10-07 20:01:52 +02001134 if (global.ssl_lim != 0) {
1135 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1136 err_code |= ERR_ALERT;
1137 goto out;
1138 }
1139 if (*(args[1]) == 0) {
1140 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1141 err_code |= ERR_ALERT | ERR_FATAL;
1142 goto out;
1143 }
1144 global.ssl_lim = atol(args[1]);
1145 }
William Lallemandd85f9172012-11-09 17:05:39 +01001146 else if (!strcmp(args[0], "maxcomprate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001147 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1148 goto out;
William Lallemandd85f9172012-11-09 17:05:39 +01001149 if (*(args[1]) == 0) {
1150 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1151 err_code |= ERR_ALERT | ERR_FATAL;
1152 goto out;
1153 }
1154 global.comp_rate_lim = atoi(args[1]) * 1024;
1155 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001156 else if (!strcmp(args[0], "maxpipes")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001157 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1158 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001159 if (global.maxpipes != 0) {
1160 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001161 err_code |= ERR_ALERT;
1162 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001163 }
1164 if (*(args[1]) == 0) {
1165 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001166 err_code |= ERR_ALERT | ERR_FATAL;
1167 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001168 }
1169 global.maxpipes = atol(args[1]);
1170 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001171 else if (!strcmp(args[0], "maxzlibmem")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001172 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1173 goto out;
William Lallemand9d5f5482012-11-07 16:12:57 +01001174 if (*(args[1]) == 0) {
1175 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1176 err_code |= ERR_ALERT | ERR_FATAL;
1177 goto out;
1178 }
William Lallemande3a7d992012-11-20 11:25:20 +01001179 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001180 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001181 else if (!strcmp(args[0], "maxcompcpuusage")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001182 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1183 goto out;
William Lallemand072a2bf2012-11-20 17:01:01 +01001184 if (*(args[1]) == 0) {
1185 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1186 err_code |= ERR_ALERT | ERR_FATAL;
1187 goto out;
1188 }
1189 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001190 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001191 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1192 err_code |= ERR_ALERT | ERR_FATAL;
1193 goto out;
1194 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001195 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001196
Willy Tarreaubaaee002006-06-26 02:48:02 +02001197 else if (!strcmp(args[0], "ulimit-n")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001198 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1199 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001200 if (global.rlimit_nofile != 0) {
1201 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001202 err_code |= ERR_ALERT;
1203 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001204 }
1205 if (*(args[1]) == 0) {
1206 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001207 err_code |= ERR_ALERT | ERR_FATAL;
1208 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001209 }
1210 global.rlimit_nofile = atol(args[1]);
1211 }
1212 else if (!strcmp(args[0], "chroot")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001213 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1214 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001215 if (global.chroot != NULL) {
1216 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001217 err_code |= ERR_ALERT;
1218 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001219 }
1220 if (*(args[1]) == 0) {
1221 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001222 err_code |= ERR_ALERT | ERR_FATAL;
1223 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001224 }
1225 global.chroot = strdup(args[1]);
1226 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001227 else if (!strcmp(args[0], "description")) {
1228 int i, len=0;
1229 char *d;
1230
1231 if (!*args[1]) {
1232 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1233 file, linenum, args[0]);
1234 err_code |= ERR_ALERT | ERR_FATAL;
1235 goto out;
1236 }
1237
Willy Tarreau348acfe2014-04-14 15:00:39 +02001238 for (i = 1; *args[i]; i++)
1239 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001240
1241 if (global.desc)
1242 free(global.desc);
1243
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001244 global.desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001245
Willy Tarreau348acfe2014-04-14 15:00:39 +02001246 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1247 for (i = 2; *args[i]; i++)
1248 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001249 }
1250 else if (!strcmp(args[0], "node")) {
1251 int i;
1252 char c;
1253
William Lallemand1a748ae2015-05-19 16:37:23 +02001254 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1255 goto out;
1256
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001257 for (i=0; args[1][i]; i++) {
1258 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001259 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1260 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001261 break;
1262 }
1263
1264 if (!i || args[1][i]) {
1265 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1266 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1267 file, linenum, args[0]);
1268 err_code |= ERR_ALERT | ERR_FATAL;
1269 goto out;
1270 }
1271
1272 if (global.node)
1273 free(global.node);
1274
1275 global.node = strdup(args[1]);
1276 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001277 else if (!strcmp(args[0], "pidfile")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001278 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1279 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001280 if (global.pidfile != NULL) {
1281 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001282 err_code |= ERR_ALERT;
1283 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001284 }
1285 if (*(args[1]) == 0) {
1286 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001287 err_code |= ERR_ALERT | ERR_FATAL;
1288 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001289 }
1290 global.pidfile = strdup(args[1]);
1291 }
Emeric Bruned760922010-10-22 17:59:25 +02001292 else if (!strcmp(args[0], "unix-bind")) {
1293 int cur_arg = 1;
1294 while (*(args[cur_arg])) {
1295 if (!strcmp(args[cur_arg], "prefix")) {
1296 if (global.unix_bind.prefix != NULL) {
1297 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1298 err_code |= ERR_ALERT;
1299 cur_arg += 2;
1300 continue;
1301 }
1302
1303 if (*(args[cur_arg+1]) == 0) {
1304 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1305 err_code |= ERR_ALERT | ERR_FATAL;
1306 goto out;
1307 }
1308 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1309 cur_arg += 2;
1310 continue;
1311 }
1312
1313 if (!strcmp(args[cur_arg], "mode")) {
1314
1315 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1316 cur_arg += 2;
1317 continue;
1318 }
1319
1320 if (!strcmp(args[cur_arg], "uid")) {
1321
1322 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1323 cur_arg += 2;
1324 continue;
1325 }
1326
1327 if (!strcmp(args[cur_arg], "gid")) {
1328
1329 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1330 cur_arg += 2;
1331 continue;
1332 }
1333
1334 if (!strcmp(args[cur_arg], "user")) {
1335 struct passwd *user;
1336
1337 user = getpwnam(args[cur_arg + 1]);
1338 if (!user) {
1339 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1340 file, linenum, args[0], args[cur_arg + 1 ]);
1341 err_code |= ERR_ALERT | ERR_FATAL;
1342 goto out;
1343 }
1344
1345 global.unix_bind.ux.uid = user->pw_uid;
1346 cur_arg += 2;
1347 continue;
1348 }
1349
1350 if (!strcmp(args[cur_arg], "group")) {
1351 struct group *group;
1352
1353 group = getgrnam(args[cur_arg + 1]);
1354 if (!group) {
1355 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1356 file, linenum, args[0], args[cur_arg + 1 ]);
1357 err_code |= ERR_ALERT | ERR_FATAL;
1358 goto out;
1359 }
1360
1361 global.unix_bind.ux.gid = group->gr_gid;
1362 cur_arg += 2;
1363 continue;
1364 }
1365
Willy Tarreaub48f9582011-09-05 01:17:06 +02001366 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001367 file, linenum, args[0]);
1368 err_code |= ERR_ALERT | ERR_FATAL;
1369 goto out;
1370 }
1371 }
William Lallemand0f99e342011-10-12 17:50:54 +02001372 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1373 /* delete previous herited or defined syslog servers */
1374 struct logsrv *back;
1375 struct logsrv *tmp;
1376
1377 if (*(args[1]) != 0) {
1378 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1379 err_code |= ERR_ALERT | ERR_FATAL;
1380 goto out;
1381 }
1382
1383 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1384 LIST_DEL(&tmp->list);
1385 free(tmp);
1386 }
1387 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001388 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001389 struct sockaddr_storage *sk;
1390 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001391 struct logsrv *logsrv;
Willy Tarreau18324f52014-06-27 18:10:07 +02001392 int arg = 0;
1393 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001394
William Lallemand1a748ae2015-05-19 16:37:23 +02001395 if (alertif_too_many_args(8, file, linenum, args, &err_code)) /* does not strictly check optional arguments */
1396 goto out;
1397
Willy Tarreaubaaee002006-06-26 02:48:02 +02001398 if (*(args[1]) == 0 || *(args[2]) == 0) {
1399 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001400 err_code |= ERR_ALERT | ERR_FATAL;
1401 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001402 }
William Lallemand0f99e342011-10-12 17:50:54 +02001403
Vincent Bernat02779b62016-04-03 13:48:43 +02001404 logsrv = calloc(1, sizeof(*logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001405
Willy Tarreau18324f52014-06-27 18:10:07 +02001406 /* just after the address, a length may be specified */
1407 if (strcmp(args[arg+2], "len") == 0) {
1408 len = atoi(args[arg+3]);
1409 if (len < 80 || len > 65535) {
1410 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1411 file, linenum, args[arg+3]);
1412 err_code |= ERR_ALERT | ERR_FATAL;
1413 goto out;
1414 }
1415 logsrv->maxlen = len;
1416
1417 /* skip these two args */
1418 arg += 2;
1419 }
1420 else
1421 logsrv->maxlen = MAX_SYSLOG_LEN;
1422
1423 if (logsrv->maxlen > global.max_syslog_len) {
1424 global.max_syslog_len = logsrv->maxlen;
Hubert Verstraete831962e2016-06-28 22:44:26 +02001425 logheader = my_realloc2(logheader, global.max_syslog_len + 1);
1426 logheader_rfc5424 = my_realloc2(logheader_rfc5424, global.max_syslog_len + 1);
1427 logline = my_realloc2(logline, global.max_syslog_len + 1);
1428 logline_rfc5424 = my_realloc2(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02001429 }
1430
Dragan Dosen1322d092015-09-22 16:05:32 +02001431 /* after the length, a format may be specified */
1432 if (strcmp(args[arg+2], "format") == 0) {
1433 logsrv->format = get_log_format(args[arg+3]);
1434 if (logsrv->format < 0) {
1435 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
1436 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01001437 free(logsrv);
Dragan Dosen1322d092015-09-22 16:05:32 +02001438 goto out;
1439 }
1440
1441 /* skip these two args */
1442 arg += 2;
1443 }
1444
David Carlier97880bb2016-04-08 10:35:26 +01001445 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code)) {
1446 free(logsrv);
William Lallemand1a748ae2015-05-19 16:37:23 +02001447 goto out;
David Carlier97880bb2016-04-08 10:35:26 +01001448 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001449
Willy Tarreau18324f52014-06-27 18:10:07 +02001450 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001451 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001452 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001453 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001454 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001455 }
1456
William Lallemand0f99e342011-10-12 17:50:54 +02001457 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02001458 if (*(args[arg+3])) {
1459 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001460 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001461 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001462 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001463 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001464 }
1465 }
1466
William Lallemand0f99e342011-10-12 17:50:54 +02001467 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02001468 if (*(args[arg+4])) {
1469 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001470 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001471 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001472 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001473 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001474 }
1475 }
1476
Willy Tarreau48ef4c92017-01-06 18:32:38 +01001477 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001478 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001479 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001480 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001481 free(logsrv);
1482 goto out;
1483 }
1484 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001485
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001486 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001487 if (port1 != port2) {
1488 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1489 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001490 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001491 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001492 goto out;
1493 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001494
William Lallemand0f99e342011-10-12 17:50:54 +02001495 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001496 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001497 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001498 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001499
William Lallemand0f99e342011-10-12 17:50:54 +02001500 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001501 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001502 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1503 char *name;
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001504
1505 if (global.log_send_hostname != NULL) {
1506 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1507 err_code |= ERR_ALERT;
1508 goto out;
1509 }
1510
1511 if (*(args[1]))
1512 name = args[1];
1513 else
1514 name = hostname;
1515
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001516 free(global.log_send_hostname);
Dragan Dosenc8cfa7b2015-09-28 13:28:21 +02001517 global.log_send_hostname = strdup(name);
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001518 }
Baptiste Assmann6bc89362015-08-23 09:22:25 +02001519 else if (!strcmp(args[0], "server-state-base")) { /* path base where HAProxy can find server state files */
1520 if (global.server_state_base != NULL) {
1521 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1522 err_code |= ERR_ALERT;
1523 goto out;
1524 }
1525
1526 if (!*(args[1])) {
1527 Alert("parsing [%s:%d] : '%s' expects one argument: a directory path.\n", file, linenum, args[0]);
1528 err_code |= ERR_FATAL;
1529 goto out;
1530 }
1531
1532 global.server_state_base = strdup(args[1]);
1533 }
Baptiste Assmanne0882262015-08-23 09:54:31 +02001534 else if (!strcmp(args[0], "server-state-file")) { /* path to the file where HAProxy can load the server states */
1535 if (global.server_state_file != NULL) {
1536 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1537 err_code |= ERR_ALERT;
1538 goto out;
1539 }
1540
1541 if (!*(args[1])) {
1542 Alert("parsing [%s:%d] : '%s' expect one argument: a file path.\n", file, linenum, args[0]);
1543 err_code |= ERR_FATAL;
1544 goto out;
1545 }
1546
1547 global.server_state_file = strdup(args[1]);
1548 }
Kevinm48936af2010-12-22 16:08:21 +00001549 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
William Lallemand1a748ae2015-05-19 16:37:23 +02001550 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1551 goto out;
Kevinm48936af2010-12-22 16:08:21 +00001552 if (*(args[1]) == 0) {
1553 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1554 err_code |= ERR_ALERT | ERR_FATAL;
1555 goto out;
1556 }
Dragan Dosen43885c72015-10-01 13:18:13 +02001557 chunk_destroy(&global.log_tag);
1558 chunk_initstr(&global.log_tag, strdup(args[1]));
Kevinm48936af2010-12-22 16:08:21 +00001559 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001560 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
William Lallemand1a748ae2015-05-19 16:37:23 +02001561 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1562 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001563 if (global.spread_checks != 0) {
1564 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001565 err_code |= ERR_ALERT;
1566 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001567 }
1568 if (*(args[1]) == 0) {
1569 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001570 err_code |= ERR_ALERT | ERR_FATAL;
1571 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001572 }
1573 global.spread_checks = atol(args[1]);
1574 if (global.spread_checks < 0 || global.spread_checks > 50) {
1575 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001576 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001577 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001578 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001579 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1580 const char *err;
1581 unsigned int val;
1582
William Lallemand1a748ae2015-05-19 16:37:23 +02001583 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1584 goto out;
Willy Tarreau1746eec2014-04-25 10:46:47 +02001585 if (*(args[1]) == 0) {
1586 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1587 err_code |= ERR_ALERT | ERR_FATAL;
1588 goto out;
1589 }
1590
1591 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1592 if (err) {
1593 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1594 err_code |= ERR_ALERT | ERR_FATAL;
1595 }
1596 global.max_spread_checks = val;
1597 if (global.max_spread_checks < 0) {
1598 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1599 err_code |= ERR_ALERT | ERR_FATAL;
1600 }
1601 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001602 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1603#ifdef USE_CPU_AFFINITY
1604 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001605 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001606 unsigned long cpus = 0;
1607
1608 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001609 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001610 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001611 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001612 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001613 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001614 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001615 proc = atol(args[1]);
1616 if (proc >= 1 && proc <= LONGBITS)
1617 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001618 }
1619
1620 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001621 Alert("parsing [%s:%d]: %s expects a process number including 'all', 'odd', 'even', or a number from 1 to %d, followed by a list of CPU ranges with numbers from 0 to %d.\n",
1622 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001623 err_code |= ERR_ALERT | ERR_FATAL;
1624 goto out;
1625 }
1626
1627 cur_arg = 2;
1628 while (*args[cur_arg]) {
1629 unsigned int low, high;
1630
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001631 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001632 char *dash = strchr(args[cur_arg], '-');
1633
1634 low = high = str2uic(args[cur_arg]);
1635 if (dash)
1636 high = str2uic(dash + 1);
1637
1638 if (high < low) {
1639 unsigned int swap = low;
1640 low = high;
1641 high = swap;
1642 }
1643
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001644 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001645 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001646 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001647 err_code |= ERR_ALERT | ERR_FATAL;
1648 goto out;
1649 }
1650
1651 while (low <= high)
1652 cpus |= 1UL << low++;
1653 }
1654 else {
1655 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1656 file, linenum, args[0], args[cur_arg]);
1657 err_code |= ERR_ALERT | ERR_FATAL;
1658 goto out;
1659 }
1660 cur_arg++;
1661 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001662 for (i = 0; i < LONGBITS; i++)
1663 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001664 global.cpu_map[i] = cpus;
1665#else
1666 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1667 err_code |= ERR_ALERT | ERR_FATAL;
1668 goto out;
1669#endif
1670 }
Willy Tarreau1d549722016-02-16 12:41:57 +01001671 else if (strcmp(args[0], "setenv") == 0 || strcmp(args[0], "presetenv") == 0) {
1672 if (alertif_too_many_args(3, file, linenum, args, &err_code))
1673 goto out;
1674
1675 if (*(args[2]) == 0) {
1676 Alert("parsing [%s:%d]: '%s' expects a name and a value.\n", file, linenum, args[0]);
1677 err_code |= ERR_ALERT | ERR_FATAL;
1678 goto out;
1679 }
1680
1681 /* "setenv" overwrites, "presetenv" only sets if not yet set */
1682 if (setenv(args[1], args[2], (args[0][0] == 's')) != 0) {
1683 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[1], strerror(errno));
1684 err_code |= ERR_ALERT | ERR_FATAL;
1685 goto out;
1686 }
1687 }
1688 else if (!strcmp(args[0], "unsetenv")) {
1689 int arg;
1690
1691 if (*(args[1]) == 0) {
1692 Alert("parsing [%s:%d]: '%s' expects at least one variable name.\n", file, linenum, args[0]);
1693 err_code |= ERR_ALERT | ERR_FATAL;
1694 goto out;
1695 }
1696
1697 for (arg = 1; *args[arg]; arg++) {
1698 if (unsetenv(args[arg]) != 0) {
1699 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[arg], strerror(errno));
1700 err_code |= ERR_ALERT | ERR_FATAL;
1701 goto out;
1702 }
1703 }
1704 }
1705 else if (!strcmp(args[0], "resetenv")) {
1706 extern char **environ;
1707 char **env = environ;
1708
1709 /* args contain variable names to keep, one per argument */
1710 while (*env) {
1711 int arg;
1712
1713 /* look for current variable in among all those we want to keep */
1714 for (arg = 1; *args[arg]; arg++) {
1715 if (strncmp(*env, args[arg], strlen(args[arg])) == 0 &&
1716 (*env)[strlen(args[arg])] == '=')
1717 break;
1718 }
1719
1720 /* delete this variable */
1721 if (!*args[arg]) {
1722 char *delim = strchr(*env, '=');
1723
1724 if (!delim || delim - *env >= trash.size) {
1725 Alert("parsing [%s:%d]: '%s' failed to unset invalid variable '%s'.\n", file, linenum, args[0], *env);
1726 err_code |= ERR_ALERT | ERR_FATAL;
1727 goto out;
1728 }
1729
1730 memcpy(trash.str, *env, delim - *env);
1731 trash.str[delim - *env] = 0;
1732
1733 if (unsetenv(trash.str) != 0) {
1734 Alert("parsing [%s:%d]: '%s' failed to unset variable '%s' : %s.\n", file, linenum, args[0], *env, strerror(errno));
1735 err_code |= ERR_ALERT | ERR_FATAL;
1736 goto out;
1737 }
1738 }
1739 else
1740 env++;
1741 }
1742 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001743 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001744 struct cfg_kw_list *kwl;
1745 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001746 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001747
1748 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1749 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1750 if (kwl->kw[index].section != CFG_GLOBAL)
1751 continue;
1752 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001753 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001754 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001755 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001756 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001757 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001758 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001759 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001760 err_code |= ERR_WARN;
1761 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001762 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001763 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001764 }
1765 }
1766 }
1767
Willy Tarreaubaaee002006-06-26 02:48:02 +02001768 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001769 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001770 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001771
Willy Tarreau058e9072009-07-20 09:30:05 +02001772 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001773 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001774 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001775}
1776
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001777void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001778{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001779 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001780 defproxy.mode = PR_MODE_TCP;
1781 defproxy.state = PR_STNEW;
1782 defproxy.maxconn = cfg_maxpconn;
1783 defproxy.conn_retries = CONN_RETRIES;
Joseph Lynch726ab712015-05-11 23:25:34 -07001784 defproxy.redispatch_after = 0;
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04001785 defproxy.lbprm.chash.balance_factor = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001786
Simon Horman66183002013-02-23 10:16:43 +09001787 defproxy.defsrv.check.inter = DEF_CHKINTR;
1788 defproxy.defsrv.check.fastinter = 0;
1789 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001790 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1791 defproxy.defsrv.agent.fastinter = 0;
1792 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001793 defproxy.defsrv.check.rise = DEF_RISETIME;
1794 defproxy.defsrv.check.fall = DEF_FALLTIME;
1795 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1796 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001797 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001798 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001799 defproxy.defsrv.maxqueue = 0;
1800 defproxy.defsrv.minconn = 0;
1801 defproxy.defsrv.maxconn = 0;
1802 defproxy.defsrv.slowstart = 0;
1803 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1804 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1805 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Simon Horman64e34162015-02-06 11:11:57 +09001806
1807 defproxy.email_alert.level = LOG_ALERT;
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02001808 defproxy.load_server_state_from_file = PR_SRV_STATE_FILE_UNSPEC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001809}
1810
Willy Tarreauade5ec42010-01-28 19:33:49 +01001811
Willy Tarreau63af98d2014-05-18 08:11:41 +02001812/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1813 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1814 * ERR_FATAL in case of error.
1815 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001816static int create_cond_regex_rule(const char *file, int line,
1817 struct proxy *px, int dir, int action, int flags,
1818 const char *cmd, const char *reg, const char *repl,
1819 const char **cond_start)
1820{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001821 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001822 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001823 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001824 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001825 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001826 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001827 int cs;
1828 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001829
1830 if (px == &defproxy) {
1831 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001832 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001833 goto err;
1834 }
1835
1836 if (*reg == 0) {
1837 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001838 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001839 goto err;
1840 }
1841
Christopher Faulet898566e2016-10-26 11:06:28 +02001842 if (warnifnotcap(px, PR_CAP_FE | PR_CAP_BE, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001843 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001844
Willy Tarreau5321c422010-01-28 20:35:13 +01001845 if (cond_start &&
1846 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001847 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1848 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1849 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001850 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001851 goto err;
1852 }
1853 }
1854 else if (cond_start && **cond_start) {
1855 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1856 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001857 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001858 goto err;
1859 }
1860
Willy Tarreau63af98d2014-05-18 08:11:41 +02001861 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001862 (dir == SMP_OPT_DIR_REQ) ?
1863 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1864 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1865 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001866
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001867 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001868 if (!preg) {
1869 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001870 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001871 goto err;
1872 }
1873
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001874 cs = !(flags & REG_ICASE);
1875 cap = !(flags & REG_NOSUB);
1876 error = NULL;
1877 if (!regex_comp(reg, preg, cs, cap, &error)) {
1878 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1879 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001880 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001881 goto err;
1882 }
1883
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001884 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001885 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001886 if (repl && err) {
1887 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1888 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001889 ret_code |= ERR_ALERT | ERR_FATAL;
1890 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001891 }
1892
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001893 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001894 ret_code |= ERR_WARN;
1895
1896 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001897
Willy Tarreau63af98d2014-05-18 08:11:41 +02001898 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001899 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001900 err:
1901 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001902 free(errmsg);
1903 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001904}
1905
Willy Tarreaubaaee002006-06-26 02:48:02 +02001906/*
William Lallemand51097192015-04-14 16:35:22 +02001907 * Parse a line in a <listen>, <frontend> or <backend> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001908 * Returns the error code, 0 if OK, or any combination of :
1909 * - ERR_ABORT: must abort ASAP
1910 * - ERR_FATAL: we can continue parsing but not start the service
1911 * - ERR_WARN: a warning has been emitted
1912 * - ERR_ALERT: an alert has been emitted
1913 * Only the two first ones can stop processing, the two others are just
1914 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001915 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001916int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1917{
1918 static struct peers *curpeers = NULL;
1919 struct peer *newpeer = NULL;
1920 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001921 struct bind_conf *bind_conf;
1922 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001923 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001924 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001925
1926 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001927 if (!*args[1]) {
1928 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001929 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001930 goto out;
1931 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001932
William Lallemand6e62fb62015-04-28 16:55:23 +02001933 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1934 goto out;
1935
Emeric Brun32da3c42010-09-23 18:39:19 +02001936 err = invalid_char(args[1]);
1937 if (err) {
1938 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1939 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001940 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001941 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001942 }
1943
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02001944 for (curpeers = cfg_peers; curpeers != NULL; curpeers = curpeers->next) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001945 /*
1946 * If there are two proxies with the same name only following
1947 * combinations are allowed:
1948 */
1949 if (strcmp(curpeers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02001950 Alert("Parsing [%s:%d]: peers section '%s' has the same name as another peers section declared at %s:%d.\n",
Emeric Brun32da3c42010-09-23 18:39:19 +02001951 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02001952 err_code |= ERR_ALERT | ERR_FATAL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001953 }
1954 }
1955
Vincent Bernat02779b62016-04-03 13:48:43 +02001956 if ((curpeers = calloc(1, sizeof(*curpeers))) == NULL) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001957 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1958 err_code |= ERR_ALERT | ERR_ABORT;
1959 goto out;
1960 }
1961
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02001962 curpeers->next = cfg_peers;
1963 cfg_peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001964 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001965 curpeers->conf.line = linenum;
1966 curpeers->last_change = now.tv_sec;
1967 curpeers->id = strdup(args[1]);
Willy Tarreau77e4bd12015-05-01 20:02:17 +02001968 curpeers->state = PR_STNEW;
Emeric Brun32da3c42010-09-23 18:39:19 +02001969 }
1970 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001971 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001972 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001973 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001974
1975 if (!*args[2]) {
1976 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1977 file, linenum, args[0]);
1978 err_code |= ERR_ALERT | ERR_FATAL;
1979 goto out;
1980 }
1981
1982 err = invalid_char(args[1]);
1983 if (err) {
1984 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1985 file, linenum, *err, args[1]);
1986 err_code |= ERR_ALERT | ERR_FATAL;
1987 goto out;
1988 }
1989
Vincent Bernat02779b62016-04-03 13:48:43 +02001990 if ((newpeer = calloc(1, sizeof(*newpeer))) == NULL) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001991 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1992 err_code |= ERR_ALERT | ERR_ABORT;
1993 goto out;
1994 }
1995
1996 /* the peers are linked backwards first */
1997 curpeers->count++;
1998 newpeer->next = curpeers->remote;
1999 curpeers->remote = newpeer;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002000 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002001 newpeer->conf.line = linenum;
2002
2003 newpeer->last_change = now.tv_sec;
2004 newpeer->id = strdup(args[1]);
2005
Willy Tarreau48ef4c92017-01-06 18:32:38 +01002006 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002007 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01002008 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002009 err_code |= ERR_ALERT | ERR_FATAL;
2010 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002011 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01002012
2013 proto = protocol_by_family(sk->ss_family);
2014 if (!proto || !proto->connect) {
2015 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2016 file, linenum, args[0], args[1]);
2017 err_code |= ERR_ALERT | ERR_FATAL;
2018 goto out;
2019 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002020
2021 if (port1 != port2) {
2022 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2023 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002024 err_code |= ERR_ALERT | ERR_FATAL;
2025 goto out;
2026 }
2027
Willy Tarreau2aa38802013-02-20 19:20:59 +01002028 if (!port1) {
2029 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2030 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002031 err_code |= ERR_ALERT | ERR_FATAL;
2032 goto out;
2033 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002034
Emeric Brun32da3c42010-09-23 18:39:19 +02002035 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002036 newpeer->proto = proto;
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002037 newpeer->xprt = xprt_get(XPRT_RAW);
Willy Tarreaud02394b2012-05-11 18:32:18 +02002038 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02002039
Emeric Brun32da3c42010-09-23 18:39:19 +02002040 if (strcmp(newpeer->id, localpeer) == 0) {
2041 /* Current is local peer, it define a frontend */
2042 newpeer->local = 1;
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02002043 cfg_peers->local = newpeer;
Emeric Brun32da3c42010-09-23 18:39:19 +02002044
2045 if (!curpeers->peers_fe) {
2046 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
2047 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2048 err_code |= ERR_ALERT | ERR_ABORT;
2049 goto out;
2050 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002051
Willy Tarreau237250c2011-07-29 01:49:03 +02002052 init_new_proxy(curpeers->peers_fe);
2053 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02002054 curpeers->peers_fe->id = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002055 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
2056 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau91d96282015-03-13 15:47:26 +01002057 peers_setup_frontend(curpeers->peers_fe);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002058
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002059 bind_conf = bind_conf_alloc(curpeers->peers_fe, file, linenum, args[2], xprt_get(XPRT_RAW));
Willy Tarreau4348fad2012-09-20 16:48:07 +02002060
Willy Tarreau902636f2013-03-10 19:44:48 +01002061 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
2062 if (errmsg && *errmsg) {
2063 indent_msg(&errmsg, 2);
2064 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002065 }
2066 else
2067 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
2068 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002069 err_code |= ERR_FATAL;
2070 goto out;
2071 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02002072
2073 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01002074 l->maxaccept = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002075 l->maxconn = curpeers->peers_fe->maxconn;
2076 l->backlog = curpeers->peers_fe->backlog;
Willy Tarreau9903f0e2015-04-04 18:50:31 +02002077 l->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02002078 l->handler = process_stream;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002079 l->analysers |= curpeers->peers_fe->fe_req_ana;
2080 l->default_target = curpeers->peers_fe->default_target;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002081 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
2082 global.maxsock += l->maxconn;
2083 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002084 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01002085 else {
2086 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
2087 file, linenum, args[0], args[1],
2088 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
2089 err_code |= ERR_FATAL;
2090 goto out;
2091 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002092 }
2093 } /* neither "peer" nor "peers" */
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002094 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
2095 curpeers->state = PR_STSTOPPED;
2096 }
2097 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
2098 curpeers->state = PR_STNEW;
2099 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002100 else if (*args[0] != 0) {
2101 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2102 err_code |= ERR_ALERT | ERR_FATAL;
2103 goto out;
2104 }
2105
2106out:
Willy Tarreau902636f2013-03-10 19:44:48 +01002107 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02002108 return err_code;
2109}
2110
Baptiste Assmann325137d2015-04-13 23:40:55 +02002111/*
2112 * Parse a <resolvers> section.
2113 * Returns the error code, 0 if OK, or any combination of :
2114 * - ERR_ABORT: must abort ASAP
2115 * - ERR_FATAL: we can continue parsing but not start the service
2116 * - ERR_WARN: a warning has been emitted
2117 * - ERR_ALERT: an alert has been emitted
2118 * Only the two first ones can stop processing, the two others are just
2119 * indicators.
2120 */
2121int cfg_parse_resolvers(const char *file, int linenum, char **args, int kwm)
2122{
2123 static struct dns_resolvers *curr_resolvers = NULL;
2124 struct dns_nameserver *newnameserver = NULL;
2125 const char *err;
2126 int err_code = 0;
2127 char *errmsg = NULL;
2128
2129 if (strcmp(args[0], "resolvers") == 0) { /* new resolvers section */
2130 if (!*args[1]) {
2131 Alert("parsing [%s:%d] : missing name for resolvers section.\n", file, linenum);
2132 err_code |= ERR_ALERT | ERR_ABORT;
2133 goto out;
2134 }
2135
2136 err = invalid_char(args[1]);
2137 if (err) {
2138 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2139 file, linenum, *err, args[0], args[1]);
2140 err_code |= ERR_ALERT | ERR_ABORT;
2141 goto out;
2142 }
2143
2144 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
2145 /* Error if two resolvers owns the same name */
2146 if (strcmp(curr_resolvers->id, args[1]) == 0) {
2147 Alert("Parsing [%s:%d]: resolvers '%s' has same name as another resolvers (declared at %s:%d).\n",
2148 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2149 err_code |= ERR_ALERT | ERR_ABORT;
2150 }
2151 }
2152
Vincent Bernat02779b62016-04-03 13:48:43 +02002153 if ((curr_resolvers = calloc(1, sizeof(*curr_resolvers))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002154 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2155 err_code |= ERR_ALERT | ERR_ABORT;
2156 goto out;
2157 }
2158
2159 /* default values */
2160 LIST_ADDQ(&dns_resolvers, &curr_resolvers->list);
2161 curr_resolvers->conf.file = strdup(file);
2162 curr_resolvers->conf.line = linenum;
2163 curr_resolvers->id = strdup(args[1]);
2164 curr_resolvers->query_ids = EB_ROOT;
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002165 /* default hold period for nx, other, refuse and timeout is 30s */
2166 curr_resolvers->hold.nx = 30000;
2167 curr_resolvers->hold.other = 30000;
2168 curr_resolvers->hold.refused = 30000;
2169 curr_resolvers->hold.timeout = 30000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002170 /* default hold period for valid is 10s */
Baptiste Assmann4c5490a2015-07-14 21:42:49 +02002171 curr_resolvers->hold.valid = 10000;
2172 curr_resolvers->timeout.retry = 1000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002173 curr_resolvers->resolve_retries = 3;
Baptiste Assmann201c07f2017-05-22 15:17:15 +02002174 /* default resolution pool size */
2175 curr_resolvers->resolution_pool_size = DNS_DEFAULT_RESOLUTION_POOL_SIZE;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002176 LIST_INIT(&curr_resolvers->nameserver_list);
Baptiste Assmann201c07f2017-05-22 15:17:15 +02002177 LIST_INIT(&curr_resolvers->resolution.curr);
2178 LIST_INIT(&curr_resolvers->resolution.wait);
2179 LIST_INIT(&curr_resolvers->resolution.pool);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002180 }
2181 else if (strcmp(args[0], "nameserver") == 0) { /* nameserver definition */
2182 struct sockaddr_storage *sk;
2183 int port1, port2;
2184 struct protocol *proto;
2185
2186 if (!*args[2]) {
2187 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2188 file, linenum, args[0]);
2189 err_code |= ERR_ALERT | ERR_FATAL;
2190 goto out;
2191 }
2192
2193 err = invalid_char(args[1]);
2194 if (err) {
2195 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2196 file, linenum, *err, args[1]);
2197 err_code |= ERR_ALERT | ERR_FATAL;
2198 goto out;
2199 }
2200
Baptiste Assmanna315c552015-11-02 22:55:49 +01002201 list_for_each_entry(newnameserver, &curr_resolvers->nameserver_list, list) {
2202 /* Error if two resolvers owns the same name */
2203 if (strcmp(newnameserver->id, args[1]) == 0) {
2204 Alert("Parsing [%s:%d]: nameserver '%s' has same name as another nameserver (declared at %s:%d).\n",
2205 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2206 err_code |= ERR_ALERT | ERR_FATAL;
2207 }
2208 }
2209
Vincent Bernat02779b62016-04-03 13:48:43 +02002210 if ((newnameserver = calloc(1, sizeof(*newnameserver))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002211 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2212 err_code |= ERR_ALERT | ERR_ABORT;
2213 goto out;
2214 }
2215
2216 /* the nameservers are linked backward first */
2217 LIST_ADDQ(&curr_resolvers->nameserver_list, &newnameserver->list);
2218 curr_resolvers->count_nameservers++;
2219 newnameserver->resolvers = curr_resolvers;
2220 newnameserver->conf.file = strdup(file);
2221 newnameserver->conf.line = linenum;
2222 newnameserver->id = strdup(args[1]);
2223
Willy Tarreau48ef4c92017-01-06 18:32:38 +01002224 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002225 if (!sk) {
2226 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2227 err_code |= ERR_ALERT | ERR_FATAL;
2228 goto out;
2229 }
2230
2231 proto = protocol_by_family(sk->ss_family);
2232 if (!proto || !proto->connect) {
2233 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2234 file, linenum, args[0], args[1]);
2235 err_code |= ERR_ALERT | ERR_FATAL;
2236 goto out;
2237 }
2238
2239 if (port1 != port2) {
2240 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2241 file, linenum, args[0], args[1], args[2]);
2242 err_code |= ERR_ALERT | ERR_FATAL;
2243 goto out;
2244 }
2245
Baptiste Assmann7f43fa92016-01-21 00:59:46 +01002246 if (!port1 && !port2) {
2247 Alert("parsing [%s:%d] : '%s %s' : no UDP port specified\n",
2248 file, linenum, args[0], args[1]);
2249 err_code |= ERR_ALERT | ERR_FATAL;
2250 goto out;
2251 }
2252
Baptiste Assmann325137d2015-04-13 23:40:55 +02002253 newnameserver->addr = *sk;
2254 }
2255 else if (strcmp(args[0], "hold") == 0) { /* hold periods */
2256 const char *res;
2257 unsigned int time;
2258
2259 if (!*args[2]) {
2260 Alert("parsing [%s:%d] : '%s' expects an <event> and a <time> as arguments.\n",
2261 file, linenum, args[0]);
2262 Alert("<event> can be either 'valid', 'nx', 'refused', 'timeout', or 'other'\n");
2263 err_code |= ERR_ALERT | ERR_FATAL;
2264 goto out;
2265 }
2266 res = parse_time_err(args[2], &time, TIME_UNIT_MS);
2267 if (res) {
2268 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2269 file, linenum, *res, args[0]);
2270 err_code |= ERR_ALERT | ERR_FATAL;
2271 goto out;
2272 }
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002273 if (strcmp(args[1], "nx") == 0)
2274 curr_resolvers->hold.nx = time;
2275 else if (strcmp(args[1], "other") == 0)
2276 curr_resolvers->hold.other = time;
2277 else if (strcmp(args[1], "refused") == 0)
2278 curr_resolvers->hold.refused = time;
2279 else if (strcmp(args[1], "timeout") == 0)
2280 curr_resolvers->hold.timeout = time;
2281 else if (strcmp(args[1], "valid") == 0)
Baptiste Assmann325137d2015-04-13 23:40:55 +02002282 curr_resolvers->hold.valid = time;
2283 else {
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002284 Alert("parsing [%s:%d] : '%s' unknown <event>: '%s', expects either 'nx', 'timeout', 'valid', or 'other'.\n",
2285 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002286 err_code |= ERR_ALERT | ERR_FATAL;
2287 goto out;
2288 }
2289
2290 }
Baptiste Assmann201c07f2017-05-22 15:17:15 +02002291 else if (strcmp(args[0], "resolution_pool_size") == 0) {
2292 if (!*args[1]) {
2293 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2294 file, linenum, args[0]);
2295 err_code |= ERR_ALERT | ERR_FATAL;
2296 goto out;
2297 }
2298 curr_resolvers->resolution_pool_size = atoi(args[1]);
2299 }
Baptiste Assmann325137d2015-04-13 23:40:55 +02002300 else if (strcmp(args[0], "resolve_retries") == 0) {
2301 if (!*args[1]) {
2302 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2303 file, linenum, args[0]);
2304 err_code |= ERR_ALERT | ERR_FATAL;
2305 goto out;
2306 }
2307 curr_resolvers->resolve_retries = atoi(args[1]);
2308 }
2309 else if (strcmp(args[0], "timeout") == 0) {
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002310 if (!*args[1]) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002311 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments.\n",
2312 file, linenum, args[0]);
2313 err_code |= ERR_ALERT | ERR_FATAL;
2314 goto out;
2315 }
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002316 else if (strcmp(args[1], "retry") == 0) {
2317 const char *res;
2318 unsigned int timeout_retry;
2319
2320 if (!*args[2]) {
2321 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2322 file, linenum, args[0], args[1]);
2323 err_code |= ERR_ALERT | ERR_FATAL;
2324 goto out;
2325 }
2326 res = parse_time_err(args[2], &timeout_retry, TIME_UNIT_MS);
2327 if (res) {
2328 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s %s>.\n",
2329 file, linenum, *res, args[0], args[1]);
2330 err_code |= ERR_ALERT | ERR_FATAL;
2331 goto out;
2332 }
2333 curr_resolvers->timeout.retry = timeout_retry;
2334 }
2335 else {
2336 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments got '%s'.\n",
2337 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002338 err_code |= ERR_ALERT | ERR_FATAL;
2339 goto out;
2340 }
Baptiste Assmann325137d2015-04-13 23:40:55 +02002341 } /* neither "nameserver" nor "resolvers" */
2342 else if (*args[0] != 0) {
2343 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2344 err_code |= ERR_ALERT | ERR_FATAL;
2345 goto out;
2346 }
2347
2348 out:
2349 free(errmsg);
2350 return err_code;
2351}
Simon Horman0d16a402015-01-30 11:22:58 +09002352
2353/*
William Lallemand51097192015-04-14 16:35:22 +02002354 * Parse a line in a <listen>, <frontend> or <backend> section.
Simon Horman0d16a402015-01-30 11:22:58 +09002355 * Returns the error code, 0 if OK, or any combination of :
2356 * - ERR_ABORT: must abort ASAP
2357 * - ERR_FATAL: we can continue parsing but not start the service
2358 * - ERR_WARN: a warning has been emitted
2359 * - ERR_ALERT: an alert has been emitted
2360 * Only the two first ones can stop processing, the two others are just
2361 * indicators.
2362 */
2363int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
2364{
2365 static struct mailers *curmailers = NULL;
2366 struct mailer *newmailer = NULL;
2367 const char *err;
2368 int err_code = 0;
2369 char *errmsg = NULL;
2370
2371 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
2372 if (!*args[1]) {
2373 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
2374 err_code |= ERR_ALERT | ERR_ABORT;
2375 goto out;
2376 }
2377
2378 err = invalid_char(args[1]);
2379 if (err) {
2380 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2381 file, linenum, *err, args[0], args[1]);
2382 err_code |= ERR_ALERT | ERR_ABORT;
2383 goto out;
2384 }
2385
2386 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
2387 /*
2388 * If there are two proxies with the same name only following
2389 * combinations are allowed:
2390 */
2391 if (strcmp(curmailers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002392 Alert("Parsing [%s:%d]: mailers section '%s' has the same name as another mailers section declared at %s:%d.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002393 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002394 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman0d16a402015-01-30 11:22:58 +09002395 }
2396 }
2397
Vincent Bernat02779b62016-04-03 13:48:43 +02002398 if ((curmailers = calloc(1, sizeof(*curmailers))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002399 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2400 err_code |= ERR_ALERT | ERR_ABORT;
2401 goto out;
2402 }
2403
2404 curmailers->next = mailers;
2405 mailers = curmailers;
2406 curmailers->conf.file = strdup(file);
2407 curmailers->conf.line = linenum;
2408 curmailers->id = strdup(args[1]);
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002409 curmailers->timeout.mail = DEF_MAILALERTTIME;/* XXX: Would like to Skip to the next alert, if any, ASAP.
2410 * But need enough time so that timeouts don't occur
2411 * during tcp procssing. For now just us an arbitrary default. */
Simon Horman0d16a402015-01-30 11:22:58 +09002412 }
2413 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
2414 struct sockaddr_storage *sk;
2415 int port1, port2;
2416 struct protocol *proto;
2417
2418 if (!*args[2]) {
2419 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2420 file, linenum, args[0]);
2421 err_code |= ERR_ALERT | ERR_FATAL;
2422 goto out;
2423 }
2424
2425 err = invalid_char(args[1]);
2426 if (err) {
2427 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2428 file, linenum, *err, args[1]);
2429 err_code |= ERR_ALERT | ERR_FATAL;
2430 goto out;
2431 }
2432
Vincent Bernat02779b62016-04-03 13:48:43 +02002433 if ((newmailer = calloc(1, sizeof(*newmailer))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002434 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2435 err_code |= ERR_ALERT | ERR_ABORT;
2436 goto out;
2437 }
2438
2439 /* the mailers are linked backwards first */
2440 curmailers->count++;
2441 newmailer->next = curmailers->mailer_list;
2442 curmailers->mailer_list = newmailer;
2443 newmailer->mailers = curmailers;
2444 newmailer->conf.file = strdup(file);
2445 newmailer->conf.line = linenum;
2446
2447 newmailer->id = strdup(args[1]);
2448
Willy Tarreau48ef4c92017-01-06 18:32:38 +01002449 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Simon Horman0d16a402015-01-30 11:22:58 +09002450 if (!sk) {
2451 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2452 err_code |= ERR_ALERT | ERR_FATAL;
2453 goto out;
2454 }
2455
2456 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002457 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2458 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002459 file, linenum, args[0], args[1]);
2460 err_code |= ERR_ALERT | ERR_FATAL;
2461 goto out;
2462 }
2463
2464 if (port1 != port2) {
2465 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2466 file, linenum, args[0], args[1], args[2]);
2467 err_code |= ERR_ALERT | ERR_FATAL;
2468 goto out;
2469 }
2470
2471 if (!port1) {
2472 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2473 file, linenum, args[0], args[1], args[2]);
2474 err_code |= ERR_ALERT | ERR_FATAL;
2475 goto out;
2476 }
2477
2478 newmailer->addr = *sk;
2479 newmailer->proto = proto;
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002480 newmailer->xprt = xprt_get(XPRT_RAW);
Simon Horman0d16a402015-01-30 11:22:58 +09002481 newmailer->sock_init_arg = NULL;
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002482 }
2483 else if (strcmp(args[0], "timeout") == 0) {
2484 if (!*args[1]) {
2485 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments.\n",
2486 file, linenum, args[0]);
2487 err_code |= ERR_ALERT | ERR_FATAL;
2488 goto out;
2489 }
2490 else if (strcmp(args[1], "mail") == 0) {
2491 const char *res;
2492 unsigned int timeout_mail;
2493 if (!*args[2]) {
2494 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2495 file, linenum, args[0], args[1]);
2496 err_code |= ERR_ALERT | ERR_FATAL;
2497 goto out;
2498 }
2499 res = parse_time_err(args[2], &timeout_mail, TIME_UNIT_MS);
2500 if (res) {
2501 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2502 file, linenum, *res, args[0]);
2503 err_code |= ERR_ALERT | ERR_FATAL;
2504 goto out;
2505 }
2506 if (timeout_mail <= 0) {
2507 Alert("parsing [%s:%d] : '%s %s' expects a positive <time> argument.\n", file, linenum, args[0], args[1]);
2508 err_code |= ERR_ALERT | ERR_FATAL;
2509 goto out;
2510 }
2511 curmailers->timeout.mail = timeout_mail;
2512 } else {
2513 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments got '%s'.\n",
2514 file, linenum, args[0], args[1]);
2515 err_code |= ERR_ALERT | ERR_FATAL;
2516 goto out;
2517 }
2518 }
Simon Horman0d16a402015-01-30 11:22:58 +09002519 else if (*args[0] != 0) {
2520 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2521 err_code |= ERR_ALERT | ERR_FATAL;
2522 goto out;
2523 }
2524
2525out:
2526 free(errmsg);
2527 return err_code;
2528}
2529
Simon Horman9dc49962015-01-30 11:22:59 +09002530static void free_email_alert(struct proxy *p)
2531{
2532 free(p->email_alert.mailers.name);
2533 p->email_alert.mailers.name = NULL;
2534 free(p->email_alert.from);
2535 p->email_alert.from = NULL;
2536 free(p->email_alert.to);
2537 p->email_alert.to = NULL;
2538 free(p->email_alert.myhostname);
2539 p->email_alert.myhostname = NULL;
2540}
2541
Willy Tarreau3842f002009-06-14 11:39:52 +02002542int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002543{
2544 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002545 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002546 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002547 int rc;
2548 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002549 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002550 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002551 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002552 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002553 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002554
Willy Tarreau977b8e42006-12-29 14:19:17 +01002555 if (!strcmp(args[0], "listen"))
2556 rc = PR_CAP_LISTEN;
2557 else if (!strcmp(args[0], "frontend"))
Christopher Faulet898566e2016-10-26 11:06:28 +02002558 rc = PR_CAP_FE;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02002559 else if (!strcmp(args[0], "backend"))
Christopher Faulet898566e2016-10-26 11:06:28 +02002560 rc = PR_CAP_BE;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002561 else
2562 rc = PR_CAP_NONE;
2563
2564 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002565 if (!*args[1]) {
2566 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
Ian Miell71c432e2015-08-18 19:32:08 +01002567 " optionally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002568 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002569 err_code |= ERR_ALERT | ERR_ABORT;
2570 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002571 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002572
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002573 err = invalid_char(args[1]);
2574 if (err) {
2575 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2576 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002577 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002578 }
2579
Willy Tarreau8f50b682015-05-26 11:45:02 +02002580 curproxy = (rc & PR_CAP_FE) ? proxy_fe_by_name(args[1]) : proxy_be_by_name(args[1]);
2581 if (curproxy) {
2582 Alert("Parsing [%s:%d]: %s '%s' has the same name as %s '%s' declared at %s:%d.\n",
2583 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2584 curproxy->id, curproxy->conf.file, curproxy->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002585 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002586 }
2587
Vincent Bernat02779b62016-04-03 13:48:43 +02002588 if ((curproxy = calloc(1, sizeof(*curproxy))) == NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002589 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002590 err_code |= ERR_ALERT | ERR_ABORT;
2591 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002592 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002593
Willy Tarreau97cb7802010-01-03 20:23:58 +01002594 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002595 curproxy->next = proxy;
2596 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002597 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2598 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002599 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002600 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002601 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002602 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002603
William Lallemand6e62fb62015-04-28 16:55:23 +02002604 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2605 if (curproxy->cap & PR_CAP_FE)
2606 Alert("parsing [%s:%d] : please use the 'bind' keyword for listening addresses.\n", file, linenum);
2607 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002608 }
2609
2610 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002611 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002612 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002613
Willy Tarreaubaaee002006-06-26 02:48:02 +02002614 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002615 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002616 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002617 curproxy->no_options = defproxy.no_options;
2618 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002619 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002620 curproxy->except_net = defproxy.except_net;
2621 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002622 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002623 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002624
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002625 if (defproxy.fwdfor_hdr_len) {
2626 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2627 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2628 }
2629
Willy Tarreaub86db342009-11-30 11:50:16 +01002630 if (defproxy.orgto_hdr_len) {
2631 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2632 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2633 }
2634
Mark Lamourinec2247f02012-01-04 13:02:01 -05002635 if (defproxy.server_id_hdr_len) {
2636 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2637 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2638 }
2639
Willy Tarreau977b8e42006-12-29 14:19:17 +01002640 if (curproxy->cap & PR_CAP_FE) {
2641 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002642 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002643 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002644
2645 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002646 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2647 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002648
2649 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2650 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002651
Willy Tarreau977b8e42006-12-29 14:19:17 +01002652 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002653 curproxy->lbprm.algo = defproxy.lbprm.algo;
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04002654 curproxy->lbprm.chash.balance_factor = defproxy.lbprm.chash.balance_factor;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002655 curproxy->fullconn = defproxy.fullconn;
2656 curproxy->conn_retries = defproxy.conn_retries;
Joseph Lynch726ab712015-05-11 23:25:34 -07002657 curproxy->redispatch_after = defproxy.redispatch_after;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002658 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002659
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002660 if (defproxy.check_req) {
2661 curproxy->check_req = calloc(1, defproxy.check_len);
2662 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2663 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002664 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002665
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002666 if (defproxy.expect_str) {
2667 curproxy->expect_str = strdup(defproxy.expect_str);
2668 if (defproxy.expect_regex) {
2669 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002670 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2671 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002672 }
2673 }
2674
Willy Tarreau67402132012-05-31 20:40:20 +02002675 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002676 if (defproxy.cookie_name)
2677 curproxy->cookie_name = strdup(defproxy.cookie_name);
2678 curproxy->cookie_len = defproxy.cookie_len;
Olivier Houchard4e694042017-03-14 20:01:29 +01002679
2680 if (defproxy.dyncookie_key)
2681 curproxy->dyncookie_key = strdup(defproxy.dyncookie_key);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002682 if (defproxy.cookie_domain)
2683 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002684
Willy Tarreau31936852010-10-06 16:59:56 +02002685 if (defproxy.cookie_maxidle)
2686 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2687
2688 if (defproxy.cookie_maxlife)
2689 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2690
Emeric Brun647caf12009-06-30 17:57:00 +02002691 if (defproxy.rdp_cookie_name)
2692 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2693 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2694
Willy Tarreau01732802007-11-01 22:48:15 +01002695 if (defproxy.url_param_name)
2696 curproxy->url_param_name = strdup(defproxy.url_param_name);
2697 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002698
Benoitaffb4812009-03-25 13:02:10 +01002699 if (defproxy.hh_name)
2700 curproxy->hh_name = strdup(defproxy.hh_name);
2701 curproxy->hh_len = defproxy.hh_len;
2702 curproxy->hh_match_domain = defproxy.hh_match_domain;
2703
Willy Tarreauef9a3602012-12-08 22:29:20 +01002704 if (defproxy.conn_src.iface_name)
2705 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2706 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002707 curproxy->conn_src.opts = defproxy.conn_src.opts;
Willy Tarreau29fbe512015-08-20 19:35:14 +02002708#if defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002709 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002710#endif
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02002711 curproxy->load_server_state_from_file = defproxy.load_server_state_from_file;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002712 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002713
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002714 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002715 if (defproxy.capture_name)
2716 curproxy->capture_name = strdup(defproxy.capture_name);
2717 curproxy->capture_namelen = defproxy.capture_namelen;
2718 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002719 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002720
Willy Tarreau977b8e42006-12-29 14:19:17 +01002721 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002722 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002723 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002724 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002725 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002726 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002727 curproxy->mon_net = defproxy.mon_net;
2728 curproxy->mon_mask = defproxy.mon_mask;
2729 if (defproxy.monitor_uri)
2730 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2731 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002732 if (defproxy.defbe.name)
2733 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002734
2735 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002736 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2737 if (curproxy->conf.logformat_string &&
2738 curproxy->conf.logformat_string != default_http_log_format &&
2739 curproxy->conf.logformat_string != default_tcp_log_format &&
2740 curproxy->conf.logformat_string != clf_http_log_format)
2741 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2742
2743 if (defproxy.conf.lfs_file) {
2744 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2745 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2746 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002747
2748 /* get either a pointer to the logformat string for RFC5424 structured-data or a copy of it */
2749 curproxy->conf.logformat_sd_string = defproxy.conf.logformat_sd_string;
2750 if (curproxy->conf.logformat_sd_string &&
2751 curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
2752 curproxy->conf.logformat_sd_string = strdup(curproxy->conf.logformat_sd_string);
2753
2754 if (defproxy.conf.lfsd_file) {
2755 curproxy->conf.lfsd_file = strdup(defproxy.conf.lfsd_file);
2756 curproxy->conf.lfsd_line = defproxy.conf.lfsd_line;
2757 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002758 }
2759
2760 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002761 curproxy->timeout.connect = defproxy.timeout.connect;
2762 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002763 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002764 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002765 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002766 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002767 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002768 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002769 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002770 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002771 }
2772
Willy Tarreaubaaee002006-06-26 02:48:02 +02002773 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002774 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002775
2776 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002777 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02002778 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01002779 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002780 LIST_INIT(&node->list);
2781 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2782 }
2783
Willy Tarreau62a61232013-04-12 18:13:46 +02002784 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2785 if (curproxy->conf.uniqueid_format_string)
2786 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2787
Dragan Dosen43885c72015-10-01 13:18:13 +02002788 chunk_dup(&curproxy->log_tag, &defproxy.log_tag);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002789
Willy Tarreau62a61232013-04-12 18:13:46 +02002790 if (defproxy.conf.uif_file) {
2791 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2792 curproxy->conf.uif_line = defproxy.conf.uif_line;
2793 }
William Lallemanda73203e2012-03-12 12:48:57 +01002794
2795 /* copy default header unique id */
2796 if (defproxy.header_unique_id)
2797 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2798
William Lallemand82fe75c2012-10-23 10:25:10 +02002799 /* default compression options */
2800 if (defproxy.comp != NULL) {
2801 curproxy->comp = calloc(1, sizeof(struct comp));
2802 curproxy->comp->algos = defproxy.comp->algos;
2803 curproxy->comp->types = defproxy.comp->types;
2804 }
2805
Willy Tarreaubaaee002006-06-26 02:48:02 +02002806 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002807 curproxy->conf.used_listener_id = EB_ROOT;
2808 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002809
Simon Horman98637e52014-06-20 12:30:16 +09002810 if (defproxy.check_path)
2811 curproxy->check_path = strdup(defproxy.check_path);
2812 if (defproxy.check_command)
2813 curproxy->check_command = strdup(defproxy.check_command);
2814
Simon Horman9dc49962015-01-30 11:22:59 +09002815 if (defproxy.email_alert.mailers.name)
2816 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2817 if (defproxy.email_alert.from)
2818 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2819 if (defproxy.email_alert.to)
2820 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2821 if (defproxy.email_alert.myhostname)
2822 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09002823 curproxy->email_alert.level = defproxy.email_alert.level;
Cyril Bonté7e084702015-12-04 03:07:06 +01002824 curproxy->email_alert.set = defproxy.email_alert.set;
Simon Horman9dc49962015-01-30 11:22:59 +09002825
Willy Tarreau93893792009-07-23 13:19:11 +02002826 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002827 }
2828 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2829 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002830 /* FIXME-20070101: we should do this too at the end of the
2831 * config parsing to free all default values.
2832 */
William Lallemand6e62fb62015-04-28 16:55:23 +02002833 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2834 err_code |= ERR_ABORT;
2835 goto out;
2836 }
2837
Willy Tarreaua534fea2008-08-03 12:19:50 +02002838 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002839 free(defproxy.check_command);
2840 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002841 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002842 free(defproxy.rdp_cookie_name);
Olivier Houchard4e694042017-03-14 20:01:29 +01002843 free(defproxy.dyncookie_key);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002844 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002845 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002846 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002847 free(defproxy.capture_name);
2848 free(defproxy.monitor_uri);
2849 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002850 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002851 free(defproxy.fwdfor_hdr_name);
2852 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002853 free(defproxy.orgto_hdr_name);
2854 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002855 free(defproxy.server_id_hdr_name);
2856 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002857 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002858 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002859 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002860 free(defproxy.expect_regex);
2861 defproxy.expect_regex = NULL;
2862 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002863
Willy Tarreau62a61232013-04-12 18:13:46 +02002864 if (defproxy.conf.logformat_string != default_http_log_format &&
2865 defproxy.conf.logformat_string != default_tcp_log_format &&
2866 defproxy.conf.logformat_string != clf_http_log_format)
2867 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002868
Willy Tarreau62a61232013-04-12 18:13:46 +02002869 free(defproxy.conf.uniqueid_format_string);
2870 free(defproxy.conf.lfs_file);
2871 free(defproxy.conf.uif_file);
Dragan Dosen43885c72015-10-01 13:18:13 +02002872 chunk_destroy(&defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09002873 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02002874
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002875 if (defproxy.conf.logformat_sd_string != default_rfc5424_sd_log_format)
2876 free(defproxy.conf.logformat_sd_string);
2877 free(defproxy.conf.lfsd_file);
2878
Willy Tarreaua534fea2008-08-03 12:19:50 +02002879 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002880 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002881
Willy Tarreaubaaee002006-06-26 02:48:02 +02002882 /* we cannot free uri_auth because it might already be used */
2883 init_default_instance();
2884 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002885 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2886 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002887 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002888 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002889 }
2890 else if (curproxy == NULL) {
2891 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002892 err_code |= ERR_ALERT | ERR_FATAL;
2893 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002894 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002895
2896 /* update the current file and line being parsed */
2897 curproxy->conf.args.file = curproxy->conf.file;
2898 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002899
2900 /* Now let's parse the proxy-specific keywords */
Frédéric Lécailleb82f7422017-04-13 18:24:23 +02002901 if (!strcmp(args[0], "server") ||
2902 !strcmp(args[0], "default-server") ||
2903 !strcmp(args[0], "server-template")) {
Willy Tarreau272adea2014-03-31 10:39:59 +02002904 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2905 if (err_code & ERR_FATAL)
2906 goto out;
2907 }
2908 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002909 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002910 int cur_arg;
2911
Willy Tarreaubaaee002006-06-26 02:48:02 +02002912 if (curproxy == &defproxy) {
2913 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002914 err_code |= ERR_ALERT | ERR_FATAL;
2915 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002916 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002917 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002918 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002919
Willy Tarreau24709282013-03-10 21:32:12 +01002920 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002921 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002922 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002923 err_code |= ERR_ALERT | ERR_FATAL;
2924 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002925 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002926
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002927 bind_conf = bind_conf_alloc(curproxy, file, linenum, args[1], xprt_get(XPRT_RAW));
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002928
2929 /* use default settings for unix sockets */
2930 bind_conf->ux.uid = global.unix_bind.ux.uid;
2931 bind_conf->ux.gid = global.unix_bind.ux.gid;
2932 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002933
2934 /* NOTE: the following line might create several listeners if there
2935 * are comma-separated IPs or port ranges. So all further processing
2936 * will have to be applied to all listeners created after last_listen.
2937 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002938 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2939 if (errmsg && *errmsg) {
2940 indent_msg(&errmsg, 2);
2941 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002942 }
2943 else
2944 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2945 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002946 err_code |= ERR_ALERT | ERR_FATAL;
2947 goto out;
2948 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002949
Willy Tarreau4348fad2012-09-20 16:48:07 +02002950 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2951 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002952 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002953 }
2954
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002955 cur_arg = 2;
2956 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002957 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002958 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002959 char *err;
2960
Willy Tarreau26982662012-09-12 23:17:10 +02002961 kw = bind_find_kw(args[cur_arg]);
2962 if (kw) {
2963 char *err = NULL;
2964 int code;
2965
2966 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002967 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2968 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002969 cur_arg += 1 + kw->skip ;
2970 err_code |= ERR_ALERT | ERR_FATAL;
2971 goto out;
2972 }
2973
Willy Tarreau4348fad2012-09-20 16:48:07 +02002974 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002975 err_code |= code;
2976
2977 if (code) {
2978 if (err && *err) {
2979 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002980 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002981 }
2982 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002983 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2984 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002985 if (code & ERR_FATAL) {
2986 free(err);
2987 cur_arg += 1 + kw->skip;
2988 goto out;
2989 }
2990 }
2991 free(err);
2992 cur_arg += 1 + kw->skip;
2993 continue;
2994 }
2995
Willy Tarreau8638f482012-09-18 18:01:17 +02002996 err = NULL;
2997 if (!bind_dumped) {
2998 bind_dump_kws(&err);
2999 indent_msg(&err, 4);
3000 bind_dumped = 1;
3001 }
3002
3003 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
3004 file, linenum, args[0], args[1], args[cur_arg],
3005 err ? " Registered keywords :" : "", err ? err : "");
3006 free(err);
3007
Willy Tarreau93893792009-07-23 13:19:11 +02003008 err_code |= ERR_ALERT | ERR_FATAL;
3009 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01003010 }
Willy Tarreau93893792009-07-23 13:19:11 +02003011 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003012 }
3013 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01003014 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003015 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
3016 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003017 err_code |= ERR_ALERT | ERR_FATAL;
3018 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003019 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003020 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003021 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003022
Willy Tarreaubaaee002006-06-26 02:48:02 +02003023 /* flush useless bits */
3024 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02003025 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003026 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02003027 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003028 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003029 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003030
William Lallemanddf1425a2015-04-28 20:17:49 +02003031 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3032 goto out;
3033
Willy Tarreau1c47f852006-07-09 08:22:27 +02003034 if (!*args[1]) {
3035 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
3036 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003037 err_code |= ERR_ALERT | ERR_FATAL;
3038 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003039 }
3040
Willy Tarreaua534fea2008-08-03 12:19:50 +02003041 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003042 curproxy->monitor_uri_len = strlen(args[1]);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003043 curproxy->monitor_uri = calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003044 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02003045 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
3046
Willy Tarreau93893792009-07-23 13:19:11 +02003047 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003048 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003049 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
William Lallemanddf1425a2015-04-28 20:17:49 +02003050 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3051 goto out;
3052
Willy Tarreaubaaee002006-06-26 02:48:02 +02003053 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
3054 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
3055 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
3056 else {
3057 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003058 err_code |= ERR_ALERT | ERR_FATAL;
3059 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003060 }
3061 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003062 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003063 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003064
3065 if (curproxy == &defproxy) {
3066 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3067 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003068 err_code |= ERR_ALERT | ERR_FATAL;
3069 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003070 }
3071
William Lallemanddf1425a2015-04-28 20:17:49 +02003072 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3073 goto out;
3074
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003075 if (!*args[1]) {
3076 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3077 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003078 err_code |= ERR_ALERT | ERR_FATAL;
3079 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003080 }
3081
3082 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003083 curproxy->conf.id.key = curproxy->uuid;
Willy Tarreau0d1fdf72015-05-27 16:44:02 +02003084 curproxy->options |= PR_O_FORCED_ID;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003085
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003086 if (curproxy->uuid <= 0) {
3087 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003088 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003089 err_code |= ERR_ALERT | ERR_FATAL;
3090 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003091 }
3092
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003093 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
3094 if (node) {
3095 struct proxy *target = container_of(node, struct proxy, conf.id);
3096 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
3097 file, linenum, proxy_type_str(curproxy), curproxy->id,
3098 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
3099 err_code |= ERR_ALERT | ERR_FATAL;
3100 goto out;
3101 }
3102 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003103 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003104 else if (!strcmp(args[0], "description")) {
3105 int i, len=0;
3106 char *d;
3107
Cyril Bonté99ed3272010-01-24 23:29:44 +01003108 if (curproxy == &defproxy) {
3109 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3110 file, linenum, args[0]);
3111 err_code |= ERR_ALERT | ERR_FATAL;
3112 goto out;
3113 }
3114
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003115 if (!*args[1]) {
3116 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
3117 file, linenum, args[0]);
3118 return -1;
3119 }
3120
Willy Tarreau348acfe2014-04-14 15:00:39 +02003121 for (i = 1; *args[i]; i++)
3122 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003123
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003124 d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003125 curproxy->desc = d;
3126
Willy Tarreau348acfe2014-04-14 15:00:39 +02003127 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
3128 for (i = 2; *args[i]; i++)
3129 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003130
3131 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003132 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
William Lallemanddf1425a2015-04-28 20:17:49 +02003133 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3134 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003135 curproxy->state = PR_STSTOPPED;
3136 }
3137 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
William Lallemanddf1425a2015-04-28 20:17:49 +02003138 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3139 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003140 curproxy->state = PR_STNEW;
3141 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003142 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
3143 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003144 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003145
3146 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003147 unsigned int low, high;
3148
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003149 if (strcmp(args[cur_arg], "all") == 0) {
3150 set = 0;
3151 break;
3152 }
3153 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003154 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003155 }
3156 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003157 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003158 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01003159 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003160 char *dash = strchr(args[cur_arg], '-');
3161
3162 low = high = str2uic(args[cur_arg]);
3163 if (dash)
3164 high = str2uic(dash + 1);
3165
3166 if (high < low) {
3167 unsigned int swap = low;
3168 low = high;
3169 high = swap;
3170 }
3171
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003172 if (low < 1 || high > LONGBITS) {
3173 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
3174 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02003175 err_code |= ERR_ALERT | ERR_FATAL;
3176 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003177 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01003178 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003179 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003180 }
3181 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003182 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
3183 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003184 err_code |= ERR_ALERT | ERR_FATAL;
3185 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003186 }
3187 cur_arg++;
3188 }
3189 curproxy->bind_proc = set;
3190 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003191 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02003192 if (curproxy == &defproxy) {
3193 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003194 err_code |= ERR_ALERT | ERR_FATAL;
3195 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003196 }
3197
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003198 err = invalid_char(args[1]);
3199 if (err) {
3200 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
3201 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003202 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau1822e8c2017-04-12 18:54:00 +02003203 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003204 }
3205
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01003206 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003207 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
3208 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003209 err_code |= ERR_ALERT | ERR_FATAL;
3210 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003211 }
Olivier Houchard4e694042017-03-14 20:01:29 +01003212 }
3213 else if (!strcmp(args[0], "dynamic-cookie-key")) { /* Dynamic cookies secret key */
3214
3215 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3216 err_code |= ERR_WARN;
3217
3218 if (*(args[1]) == 0) {
3219 Alert("parsing [%s:%d] : '%s' expects <secret_key> as argument.\n",
3220 file, linenum, args[0]);
3221 err_code |= ERR_ALERT | ERR_FATAL;
3222 goto out;
3223 }
3224 free(curproxy->dyncookie_key);
3225 curproxy->dyncookie_key = strdup(args[1]);
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003226 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003227 else if (!strcmp(args[0], "cookie")) { /* cookie name */
3228 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003229
Willy Tarreau977b8e42006-12-29 14:19:17 +01003230 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003231 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003232
Willy Tarreaubaaee002006-06-26 02:48:02 +02003233 if (*(args[1]) == 0) {
3234 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
3235 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003236 err_code |= ERR_ALERT | ERR_FATAL;
3237 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003238 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003239
Willy Tarreau67402132012-05-31 20:40:20 +02003240 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003241 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01003242 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003243 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003244 curproxy->cookie_name = strdup(args[1]);
3245 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003246
Willy Tarreaubaaee002006-06-26 02:48:02 +02003247 cur_arg = 2;
3248 while (*(args[cur_arg])) {
3249 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003250 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003251 }
3252 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003253 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003254 }
3255 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003256 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003257 }
3258 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003259 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003260 }
3261 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003262 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003263 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003264 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003265 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003266 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003267 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003268 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003269 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02003270 else if (!strcmp(args[cur_arg], "httponly")) {
3271 curproxy->ck_opts |= PR_CK_HTTPONLY;
3272 }
3273 else if (!strcmp(args[cur_arg], "secure")) {
3274 curproxy->ck_opts |= PR_CK_SECURE;
3275 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003276 else if (!strcmp(args[cur_arg], "domain")) {
3277 if (!*args[cur_arg + 1]) {
3278 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
3279 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003280 err_code |= ERR_ALERT | ERR_FATAL;
3281 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003282 }
3283
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003284 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003285 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003286 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
3287 " dots nor does not start with a dot."
3288 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003289 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003290 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003291 }
3292
3293 err = invalid_domainchar(args[cur_arg + 1]);
3294 if (err) {
3295 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
3296 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003297 err_code |= ERR_ALERT | ERR_FATAL;
3298 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003299 }
3300
Willy Tarreau68a897b2009-12-03 23:28:34 +01003301 if (!curproxy->cookie_domain) {
3302 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
3303 } else {
3304 /* one domain was already specified, add another one by
3305 * building the string which will be returned along with
3306 * the cookie.
3307 */
3308 char *new_ptr;
3309 int new_len = strlen(curproxy->cookie_domain) +
3310 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
3311 new_ptr = malloc(new_len);
3312 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
3313 free(curproxy->cookie_domain);
3314 curproxy->cookie_domain = new_ptr;
3315 }
Willy Tarreau31936852010-10-06 16:59:56 +02003316 cur_arg++;
3317 }
3318 else if (!strcmp(args[cur_arg], "maxidle")) {
3319 unsigned int maxidle;
3320 const char *res;
3321
3322 if (!*args[cur_arg + 1]) {
3323 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
3324 file, linenum, args[cur_arg]);
3325 err_code |= ERR_ALERT | ERR_FATAL;
3326 goto out;
3327 }
3328
3329 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
3330 if (res) {
3331 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3332 file, linenum, *res, args[cur_arg]);
3333 err_code |= ERR_ALERT | ERR_FATAL;
3334 goto out;
3335 }
3336 curproxy->cookie_maxidle = maxidle;
3337 cur_arg++;
3338 }
3339 else if (!strcmp(args[cur_arg], "maxlife")) {
3340 unsigned int maxlife;
3341 const char *res;
3342
3343 if (!*args[cur_arg + 1]) {
3344 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
3345 file, linenum, args[cur_arg]);
3346 err_code |= ERR_ALERT | ERR_FATAL;
3347 goto out;
3348 }
3349
3350 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
3351 if (res) {
3352 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3353 file, linenum, *res, args[cur_arg]);
3354 err_code |= ERR_ALERT | ERR_FATAL;
3355 goto out;
3356 }
3357 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003358 cur_arg++;
3359 }
Olivier Houcharda5938f72017-03-15 15:12:06 +01003360 else if (!strcmp(args[cur_arg], "dynamic")) { /* Dynamic persistent cookies secret key */
Olivier Houchard4e694042017-03-14 20:01:29 +01003361
3362 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[cur_arg], NULL))
3363 err_code |= ERR_WARN;
3364 curproxy->ck_opts |= PR_CK_DYNAMIC;
3365 }
3366
Willy Tarreaubaaee002006-06-26 02:48:02 +02003367 else {
Olivier Houchard4e694042017-03-14 20:01:29 +01003368 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache', 'postonly', 'domain', 'maxidle', 'dynamic' and 'maxlife' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003369 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003370 err_code |= ERR_ALERT | ERR_FATAL;
3371 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003372 }
3373 cur_arg++;
3374 }
Willy Tarreau67402132012-05-31 20:40:20 +02003375 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003376 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
3377 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003378 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003379 }
3380
Willy Tarreau67402132012-05-31 20:40:20 +02003381 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003382 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
3383 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003384 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003385 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003386
Willy Tarreau67402132012-05-31 20:40:20 +02003387 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003388 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
3389 file, linenum);
3390 err_code |= ERR_ALERT | ERR_FATAL;
3391 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003392 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09003393 else if (!strcmp(args[0], "email-alert")) {
3394 if (*(args[1]) == 0) {
3395 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3396 file, linenum, args[0]);
3397 err_code |= ERR_ALERT | ERR_FATAL;
3398 goto out;
3399 }
3400
3401 if (!strcmp(args[1], "from")) {
3402 if (*(args[1]) == 0) {
3403 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3404 file, linenum, args[1]);
3405 err_code |= ERR_ALERT | ERR_FATAL;
3406 goto out;
3407 }
3408 free(curproxy->email_alert.from);
3409 curproxy->email_alert.from = strdup(args[2]);
3410 }
3411 else if (!strcmp(args[1], "mailers")) {
3412 if (*(args[1]) == 0) {
3413 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3414 file, linenum, args[1]);
3415 err_code |= ERR_ALERT | ERR_FATAL;
3416 goto out;
3417 }
3418 free(curproxy->email_alert.mailers.name);
3419 curproxy->email_alert.mailers.name = strdup(args[2]);
3420 }
3421 else if (!strcmp(args[1], "myhostname")) {
3422 if (*(args[1]) == 0) {
3423 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3424 file, linenum, args[1]);
3425 err_code |= ERR_ALERT | ERR_FATAL;
3426 goto out;
3427 }
3428 free(curproxy->email_alert.myhostname);
3429 curproxy->email_alert.myhostname = strdup(args[2]);
3430 }
Simon Horman64e34162015-02-06 11:11:57 +09003431 else if (!strcmp(args[1], "level")) {
3432 curproxy->email_alert.level = get_log_level(args[2]);
3433 if (curproxy->email_alert.level < 0) {
3434 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
3435 file, linenum, args[1], args[2]);
3436 err_code |= ERR_ALERT | ERR_FATAL;
3437 goto out;
3438 }
3439 }
Simon Horman9dc49962015-01-30 11:22:59 +09003440 else if (!strcmp(args[1], "to")) {
3441 if (*(args[1]) == 0) {
3442 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3443 file, linenum, args[1]);
3444 err_code |= ERR_ALERT | ERR_FATAL;
3445 goto out;
3446 }
3447 free(curproxy->email_alert.to);
3448 curproxy->email_alert.to = strdup(args[2]);
3449 }
3450 else {
3451 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
3452 file, linenum, args[1]);
3453 err_code |= ERR_ALERT | ERR_FATAL;
3454 goto out;
3455 }
Simon Horman64e34162015-02-06 11:11:57 +09003456 /* Indicate that the email_alert is at least partially configured */
3457 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09003458 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09003459 else if (!strcmp(args[0], "external-check")) {
3460 if (*(args[1]) == 0) {
3461 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3462 file, linenum, args[0]);
3463 err_code |= ERR_ALERT | ERR_FATAL;
3464 goto out;
3465 }
3466
3467 if (!strcmp(args[1], "command")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003468 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003469 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003470 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003471 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3472 file, linenum, args[1]);
3473 err_code |= ERR_ALERT | ERR_FATAL;
3474 goto out;
3475 }
3476 free(curproxy->check_command);
3477 curproxy->check_command = strdup(args[2]);
3478 }
3479 else if (!strcmp(args[1], "path")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003480 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003481 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003482 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003483 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3484 file, linenum, args[1]);
3485 err_code |= ERR_ALERT | ERR_FATAL;
3486 goto out;
3487 }
3488 free(curproxy->check_path);
3489 curproxy->check_path = strdup(args[2]);
3490 }
3491 else {
3492 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
3493 file, linenum, args[1]);
3494 err_code |= ERR_ALERT | ERR_FATAL;
3495 goto out;
3496 }
3497 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02003498 else if (!strcmp(args[0], "persist")) { /* persist */
3499 if (*(args[1]) == 0) {
3500 Alert("parsing [%s:%d] : missing persist method.\n",
3501 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003502 err_code |= ERR_ALERT | ERR_FATAL;
3503 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003504 }
3505
3506 if (!strncmp(args[1], "rdp-cookie", 10)) {
3507 curproxy->options2 |= PR_O2_RDPC_PRST;
3508
Emeric Brunb982a3d2010-01-04 15:45:53 +01003509 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003510 const char *beg, *end;
3511
3512 beg = args[1] + 11;
3513 end = strchr(beg, ')');
3514
William Lallemanddf1425a2015-04-28 20:17:49 +02003515 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3516 goto out;
3517
Emeric Brun647caf12009-06-30 17:57:00 +02003518 if (!end || end == beg) {
3519 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3520 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003521 err_code |= ERR_ALERT | ERR_FATAL;
3522 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003523 }
3524
3525 free(curproxy->rdp_cookie_name);
3526 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3527 curproxy->rdp_cookie_len = end-beg;
3528 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003529 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003530 free(curproxy->rdp_cookie_name);
3531 curproxy->rdp_cookie_name = strdup("msts");
3532 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3533 }
3534 else { /* syntax */
3535 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3536 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003537 err_code |= ERR_ALERT | ERR_FATAL;
3538 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003539 }
3540 }
3541 else {
3542 Alert("parsing [%s:%d] : unknown persist method.\n",
3543 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003544 err_code |= ERR_ALERT | ERR_FATAL;
3545 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003546 }
3547 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003548 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreau6db62c52015-08-10 19:04:29 +02003549 Alert("parsing [%s:%d] : '%s' is not supported anymore, please check the documentation.\n", file, linenum, args[0]);
3550 err_code |= ERR_ALERT | ERR_FATAL;
3551 goto out;
3552 }
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02003553 else if (!strcmp(args[0], "load-server-state-from-file")) {
3554 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3555 err_code |= ERR_WARN;
3556 if (!strcmp(args[1], "global")) { /* use the file pointed to by global server-state-file directive */
3557 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_GLOBAL;
3558 }
3559 else if (!strcmp(args[1], "local")) { /* use the server-state-file-name variable to locate the server-state file */
3560 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_LOCAL;
3561 }
3562 else if (!strcmp(args[1], "none")) { /* don't use server-state-file directive for this backend */
3563 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
3564 }
3565 else {
3566 Alert("parsing [%s:%d] : '%s' expects 'global', 'local' or 'none'. Got '%s'\n",
3567 file, linenum, args[0], args[1]);
3568 err_code |= ERR_ALERT | ERR_FATAL;
3569 goto out;
3570 }
3571 }
3572 else if (!strcmp(args[0], "server-state-file-name")) {
3573 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3574 err_code |= ERR_WARN;
3575 if (*(args[1]) == 0) {
3576 Alert("parsing [%s:%d] : '%s' expects 'use-backend-name' or a string. Got no argument\n",
3577 file, linenum, args[0]);
3578 err_code |= ERR_ALERT | ERR_FATAL;
3579 goto out;
3580 }
3581 else if (!strcmp(args[1], "use-backend-name"))
3582 curproxy->server_state_file_name = strdup(curproxy->id);
3583 else
3584 curproxy->server_state_file_name = strdup(args[1]);
3585 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003586 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003587 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003588 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003589
Willy Tarreaubaaee002006-06-26 02:48:02 +02003590 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003591 if (curproxy == &defproxy) {
3592 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3593 err_code |= ERR_ALERT | ERR_FATAL;
3594 goto out;
3595 }
3596
William Lallemand1a748ae2015-05-19 16:37:23 +02003597 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3598 goto out;
3599
Willy Tarreaubaaee002006-06-26 02:48:02 +02003600 if (*(args[4]) == 0) {
3601 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3602 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003603 err_code |= ERR_ALERT | ERR_FATAL;
3604 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003605 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003606 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003607 curproxy->capture_name = strdup(args[2]);
3608 curproxy->capture_namelen = strlen(curproxy->capture_name);
3609 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003610 curproxy->to_log |= LW_COOKIE;
3611 }
3612 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3613 struct cap_hdr *hdr;
3614
3615 if (curproxy == &defproxy) {
3616 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003617 err_code |= ERR_ALERT | ERR_FATAL;
3618 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003619 }
3620
William Lallemand1a748ae2015-05-19 16:37:23 +02003621 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3622 goto out;
3623
Willy Tarreaubaaee002006-06-26 02:48:02 +02003624 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3625 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3626 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003627 err_code |= ERR_ALERT | ERR_FATAL;
3628 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003629 }
3630
Vincent Bernat02779b62016-04-03 13:48:43 +02003631 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003632 hdr->next = curproxy->req_cap;
3633 hdr->name = strdup(args[3]);
3634 hdr->namelen = strlen(args[3]);
3635 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003636 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003637 hdr->index = curproxy->nb_req_cap++;
3638 curproxy->req_cap = hdr;
3639 curproxy->to_log |= LW_REQHDR;
3640 }
3641 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3642 struct cap_hdr *hdr;
3643
3644 if (curproxy == &defproxy) {
3645 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003646 err_code |= ERR_ALERT | ERR_FATAL;
3647 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003648 }
3649
William Lallemand1a748ae2015-05-19 16:37:23 +02003650 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3651 goto out;
3652
Willy Tarreaubaaee002006-06-26 02:48:02 +02003653 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3654 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3655 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003656 err_code |= ERR_ALERT | ERR_FATAL;
3657 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003658 }
Vincent Bernat02779b62016-04-03 13:48:43 +02003659 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003660 hdr->next = curproxy->rsp_cap;
3661 hdr->name = strdup(args[3]);
3662 hdr->namelen = strlen(args[3]);
3663 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003664 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003665 hdr->index = curproxy->nb_rsp_cap++;
3666 curproxy->rsp_cap = hdr;
3667 curproxy->to_log |= LW_RSPHDR;
3668 }
3669 else {
3670 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3671 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003672 err_code |= ERR_ALERT | ERR_FATAL;
3673 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003674 }
3675 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003676 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003677 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003678 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003679
William Lallemanddf1425a2015-04-28 20:17:49 +02003680 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3681 goto out;
3682
Willy Tarreaubaaee002006-06-26 02:48:02 +02003683 if (*(args[1]) == 0) {
3684 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3685 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003686 err_code |= ERR_ALERT | ERR_FATAL;
3687 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003688 }
3689 curproxy->conn_retries = atol(args[1]);
3690 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003691 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003692 struct act_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003693
3694 if (curproxy == &defproxy) {
3695 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3696 err_code |= ERR_ALERT | ERR_FATAL;
3697 goto out;
3698 }
3699
Willy Tarreau20b0de52012-12-24 15:45:22 +01003700 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003701 !LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003702 (LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3703 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_DENY ||
3704 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REDIR ||
3705 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REQ_AUTH)) {
Willy Tarreau20b0de52012-12-24 15:45:22 +01003706 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003707 file, linenum, args[0]);
3708 err_code |= ERR_WARN;
3709 }
3710
Willy Tarreauff011f22011-01-06 17:51:27 +01003711 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003712
Willy Tarreauff011f22011-01-06 17:51:27 +01003713 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003714 err_code |= ERR_ALERT | ERR_ABORT;
3715 goto out;
3716 }
3717
Willy Tarreau5002f572014-04-23 01:32:02 +02003718 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003719 err_code |= warnif_cond_conflicts(rule->cond,
3720 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3721 file, linenum);
3722
Willy Tarreauff011f22011-01-06 17:51:27 +01003723 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003724 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003725 else if (!strcmp(args[0], "http-response")) { /* response access control */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003726 struct act_rule *rule;
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003727
3728 if (curproxy == &defproxy) {
3729 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3730 err_code |= ERR_ALERT | ERR_FATAL;
3731 goto out;
3732 }
3733
3734 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003735 !LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003736 (LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3737 LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_DENY)) {
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003738 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3739 file, linenum, args[0]);
3740 err_code |= ERR_WARN;
3741 }
3742
3743 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3744
3745 if (!rule) {
3746 err_code |= ERR_ALERT | ERR_ABORT;
3747 goto out;
3748 }
3749
3750 err_code |= warnif_cond_conflicts(rule->cond,
3751 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3752 file, linenum);
3753
3754 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3755 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003756 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3757 /* set the header name and length into the proxy structure */
3758 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3759 err_code |= ERR_WARN;
3760
3761 if (!*args[1]) {
3762 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3763 file, linenum, args[0]);
3764 err_code |= ERR_ALERT | ERR_FATAL;
3765 goto out;
3766 }
3767
3768 /* set the desired header name */
3769 free(curproxy->server_id_hdr_name);
3770 curproxy->server_id_hdr_name = strdup(args[1]);
3771 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3772 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003773 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003774 struct act_rule *rule;
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003775
Willy Tarreaub099aca2008-10-12 17:26:37 +02003776 if (curproxy == &defproxy) {
3777 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003778 err_code |= ERR_ALERT | ERR_FATAL;
3779 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003780 }
3781
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003782 /* emulate "block" using "http-request block". Since these rules are supposed to
3783 * be processed before all http-request rules, we put them into their own list
3784 * and will insert them at the end.
3785 */
3786 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3787 if (!rule) {
3788 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003789 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003790 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003791 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3792 err_code |= warnif_cond_conflicts(rule->cond,
3793 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3794 file, linenum);
3795 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003796
3797 if (!already_warned(WARN_BLOCK_DEPRECATED))
3798 Warning("parsing [%s:%d] : The '%s' directive is now deprecated in favor of 'http-request deny' which uses the exact same syntax. The rules are translated but support might disappear in a future version.\n", file, linenum, args[0]);
3799
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003800 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003801 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003802 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003803
Cyril Bonté99ed3272010-01-24 23:29:44 +01003804 if (curproxy == &defproxy) {
3805 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3806 err_code |= ERR_ALERT | ERR_FATAL;
3807 goto out;
3808 }
3809
Willy Tarreaube4653b2015-05-28 15:26:58 +02003810 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003811 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3812 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003813 err_code |= ERR_ALERT | ERR_FATAL;
3814 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003815 }
3816
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003817 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003818 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003819 err_code |= warnif_cond_conflicts(rule->cond,
3820 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3821 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003822 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003823 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003824 struct switching_rule *rule;
3825
Willy Tarreaub099aca2008-10-12 17:26:37 +02003826 if (curproxy == &defproxy) {
3827 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003828 err_code |= ERR_ALERT | ERR_FATAL;
3829 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003830 }
3831
Willy Tarreau55ea7572007-06-17 19:56:27 +02003832 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003833 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003834
3835 if (*(args[1]) == 0) {
3836 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003837 err_code |= ERR_ALERT | ERR_FATAL;
3838 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003839 }
3840
Willy Tarreauf51658d2014-04-23 01:21:56 +02003841 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3842 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3843 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3844 file, linenum, errmsg);
3845 err_code |= ERR_ALERT | ERR_FATAL;
3846 goto out;
3847 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003848
Willy Tarreauf51658d2014-04-23 01:21:56 +02003849 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003850 }
Willy Tarreau4f862642017-02-28 09:34:39 +01003851 else if (*args[2]) {
3852 Alert("parsing [%s:%d] : unexpected keyword '%s' after switching rule, only 'if' and 'unless' are allowed.\n",
3853 file, linenum, args[2]);
3854 err_code |= ERR_ALERT | ERR_FATAL;
3855 goto out;
3856 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003857
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003858 rule = calloc(1, sizeof(*rule));
Thierry FOURNIER / OZON.IO5948b012016-11-24 23:58:32 +01003859 if (!rule) {
3860 Alert("Out of memory error.\n");
3861 goto out;
3862 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003863 rule->cond = cond;
3864 rule->be.name = strdup(args[1]);
Thierry FOURNIER / OZON.IO4ed1c952016-11-24 23:57:54 +01003865 rule->line = linenum;
3866 rule->file = strdup(file);
3867 if (!rule->file) {
3868 Alert("Out of memory error.\n");
3869 goto out;
3870 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003871 LIST_INIT(&rule->list);
3872 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3873 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003874 else if (strcmp(args[0], "use-server") == 0) {
3875 struct server_rule *rule;
3876
3877 if (curproxy == &defproxy) {
3878 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3879 err_code |= ERR_ALERT | ERR_FATAL;
3880 goto out;
3881 }
3882
3883 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3884 err_code |= ERR_WARN;
3885
3886 if (*(args[1]) == 0) {
3887 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3888 err_code |= ERR_ALERT | ERR_FATAL;
3889 goto out;
3890 }
3891
3892 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3893 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3894 file, linenum, args[0]);
3895 err_code |= ERR_ALERT | ERR_FATAL;
3896 goto out;
3897 }
3898
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003899 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3900 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3901 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003902 err_code |= ERR_ALERT | ERR_FATAL;
3903 goto out;
3904 }
3905
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003906 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003907
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003908 rule = calloc(1, sizeof(*rule));
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003909 rule->cond = cond;
3910 rule->srv.name = strdup(args[1]);
3911 LIST_INIT(&rule->list);
3912 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3913 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3914 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003915 else if ((!strcmp(args[0], "force-persist")) ||
3916 (!strcmp(args[0], "ignore-persist"))) {
3917 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003918
3919 if (curproxy == &defproxy) {
3920 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3921 err_code |= ERR_ALERT | ERR_FATAL;
3922 goto out;
3923 }
3924
3925 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3926 err_code |= ERR_WARN;
3927
Willy Tarreauef6494c2010-01-28 17:12:36 +01003928 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003929 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3930 file, linenum, args[0]);
3931 err_code |= ERR_ALERT | ERR_FATAL;
3932 goto out;
3933 }
3934
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003935 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3936 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3937 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003938 err_code |= ERR_ALERT | ERR_FATAL;
3939 goto out;
3940 }
3941
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003942 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3943 * where force-persist is applied.
3944 */
3945 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003946
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003947 rule = calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003948 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003949 if (!strcmp(args[0], "force-persist")) {
3950 rule->type = PERSIST_TYPE_FORCE;
3951 } else {
3952 rule->type = PERSIST_TYPE_IGNORE;
3953 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003954 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003955 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003956 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003957 else if (!strcmp(args[0], "stick-table")) {
3958 int myidx = 1;
Willy Tarreaue45288c2015-05-26 10:49:46 +02003959 struct proxy *other;
3960
Willy Tarreaue2dc1fa2015-05-26 12:08:07 +02003961 other = proxy_tbl_by_name(curproxy->id);
Willy Tarreaue45288c2015-05-26 10:49:46 +02003962 if (other) {
3963 Alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
3964 file, linenum, curproxy->id, proxy_type_str(other), other->id, other->conf.file, other->conf.line);
3965 err_code |= ERR_ALERT | ERR_FATAL;
3966 goto out;
3967 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003968
Emeric Brun32da3c42010-09-23 18:39:19 +02003969 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003970 curproxy->table.type = (unsigned int)-1;
3971 while (*args[myidx]) {
3972 const char *err;
3973
3974 if (strcmp(args[myidx], "size") == 0) {
3975 myidx++;
3976 if (!*(args[myidx])) {
3977 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3978 file, linenum, args[myidx-1]);
3979 err_code |= ERR_ALERT | ERR_FATAL;
3980 goto out;
3981 }
3982 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3983 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3984 file, linenum, *err, args[myidx-1]);
3985 err_code |= ERR_ALERT | ERR_FATAL;
3986 goto out;
3987 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003988 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003989 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003990 else if (strcmp(args[myidx], "peers") == 0) {
3991 myidx++;
Godbach50523162013-12-11 19:48:57 +08003992 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003993 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3994 file, linenum, args[myidx-1]);
3995 err_code |= ERR_ALERT | ERR_FATAL;
3996 goto out;
Godbach50523162013-12-11 19:48:57 +08003997 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003998 curproxy->table.peers.name = strdup(args[myidx++]);
3999 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004000 else if (strcmp(args[myidx], "expire") == 0) {
4001 myidx++;
4002 if (!*(args[myidx])) {
4003 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4004 file, linenum, args[myidx-1]);
4005 err_code |= ERR_ALERT | ERR_FATAL;
4006 goto out;
4007 }
4008 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
4009 if (err) {
4010 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
4011 file, linenum, *err, args[myidx-1]);
4012 err_code |= ERR_ALERT | ERR_FATAL;
4013 goto out;
4014 }
Ben Cabot3b90f0a2016-01-20 09:44:39 +00004015 if (val > INT_MAX) {
4016 Alert("parsing [%s:%d] : Expire value [%u]ms exceeds maxmimum value of 24.85 days.\n",
4017 file, linenum, val);
4018 err_code |= ERR_ALERT | ERR_FATAL;
4019 goto out;
4020 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004021 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01004022 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004023 }
4024 else if (strcmp(args[myidx], "nopurge") == 0) {
4025 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01004026 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004027 }
4028 else if (strcmp(args[myidx], "type") == 0) {
4029 myidx++;
4030 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
4031 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
4032 file, linenum, args[myidx]);
4033 err_code |= ERR_ALERT | ERR_FATAL;
4034 goto out;
4035 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004036 /* myidx already points to next arg */
4037 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004038 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02004039 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02004040 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02004041
4042 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004043 nw = args[myidx];
4044 while (*nw) {
4045 /* the "store" keyword supports a comma-separated list */
4046 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02004047 sa = NULL; /* store arg */
4048 while (*nw && *nw != ',') {
4049 if (*nw == '(') {
4050 *nw = 0;
4051 sa = ++nw;
4052 while (*nw != ')') {
4053 if (!*nw) {
4054 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
4055 file, linenum, args[0], cw);
4056 err_code |= ERR_ALERT | ERR_FATAL;
4057 goto out;
4058 }
4059 nw++;
4060 }
4061 *nw = '\0';
4062 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004063 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02004064 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004065 if (*nw)
4066 *nw++ = '\0';
4067 type = stktable_get_data_type(cw);
4068 if (type < 0) {
4069 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
4070 file, linenum, args[0], cw);
4071 err_code |= ERR_ALERT | ERR_FATAL;
4072 goto out;
4073 }
Willy Tarreauac782882010-06-20 10:41:54 +02004074
4075 err = stktable_alloc_data_type(&curproxy->table, type, sa);
4076 switch (err) {
4077 case PE_NONE: break;
4078 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004079 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
4080 file, linenum, args[0], cw);
4081 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02004082 break;
4083
4084 case PE_ARG_MISSING:
4085 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
4086 file, linenum, args[0], cw);
4087 err_code |= ERR_ALERT | ERR_FATAL;
4088 goto out;
4089
4090 case PE_ARG_NOT_USED:
4091 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
4092 file, linenum, args[0], cw);
4093 err_code |= ERR_ALERT | ERR_FATAL;
4094 goto out;
4095
4096 default:
4097 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
4098 file, linenum, args[0], cw);
4099 err_code |= ERR_ALERT | ERR_FATAL;
4100 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004101 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004102 }
4103 myidx++;
4104 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004105 else {
4106 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
4107 file, linenum, args[myidx]);
4108 err_code |= ERR_ALERT | ERR_FATAL;
4109 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004110 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004111 }
4112
4113 if (!curproxy->table.size) {
4114 Alert("parsing [%s:%d] : stick-table: missing size.\n",
4115 file, linenum);
4116 err_code |= ERR_ALERT | ERR_FATAL;
4117 goto out;
4118 }
4119
4120 if (curproxy->table.type == (unsigned int)-1) {
4121 Alert("parsing [%s:%d] : stick-table: missing type.\n",
4122 file, linenum);
4123 err_code |= ERR_ALERT | ERR_FATAL;
4124 goto out;
4125 }
4126 }
4127 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004128 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02004129 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004130 int myidx = 0;
4131 const char *name = NULL;
4132 int flags;
4133
4134 if (curproxy == &defproxy) {
4135 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4136 err_code |= ERR_ALERT | ERR_FATAL;
4137 goto out;
4138 }
4139
4140 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
4141 err_code |= ERR_WARN;
4142 goto out;
4143 }
4144
4145 myidx++;
4146 if ((strcmp(args[myidx], "store") == 0) ||
4147 (strcmp(args[myidx], "store-request") == 0)) {
4148 myidx++;
4149 flags = STK_IS_STORE;
4150 }
4151 else if (strcmp(args[myidx], "store-response") == 0) {
4152 myidx++;
4153 flags = STK_IS_STORE | STK_ON_RSP;
4154 }
4155 else if (strcmp(args[myidx], "match") == 0) {
4156 myidx++;
4157 flags = STK_IS_MATCH;
4158 }
4159 else if (strcmp(args[myidx], "on") == 0) {
4160 myidx++;
4161 flags = STK_IS_MATCH | STK_IS_STORE;
4162 }
4163 else {
4164 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
4165 err_code |= ERR_ALERT | ERR_FATAL;
4166 goto out;
4167 }
4168
4169 if (*(args[myidx]) == 0) {
4170 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
4171 err_code |= ERR_ALERT | ERR_FATAL;
4172 goto out;
4173 }
4174
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004175 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01004176 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004177 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01004178 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004179 err_code |= ERR_ALERT | ERR_FATAL;
4180 goto out;
4181 }
4182
4183 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01004184 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
4185 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
4186 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004187 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004188 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004189 goto out;
4190 }
4191 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01004192 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
4193 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
4194 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004195 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004196 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004197 goto out;
4198 }
4199 }
4200
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004201 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01004202 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004203
Emeric Brunb982a3d2010-01-04 15:45:53 +01004204 if (strcmp(args[myidx], "table") == 0) {
4205 myidx++;
4206 name = args[myidx++];
4207 }
4208
Willy Tarreauef6494c2010-01-28 17:12:36 +01004209 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004210 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
4211 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
4212 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004213 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004214 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004215 goto out;
4216 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004217 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01004218 else if (*(args[myidx])) {
4219 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
4220 file, linenum, args[0], args[myidx]);
4221 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004222 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01004223 goto out;
4224 }
Emeric Brun97679e72010-09-23 17:56:44 +02004225 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004226 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02004227 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004228 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01004229
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004230 rule = calloc(1, sizeof(*rule));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004231 rule->cond = cond;
4232 rule->expr = expr;
4233 rule->flags = flags;
4234 rule->table.name = name ? strdup(name) : NULL;
4235 LIST_INIT(&rule->list);
4236 if (flags & STK_ON_RSP)
4237 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
4238 else
4239 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
4240 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004241 else if (!strcmp(args[0], "stats")) {
4242 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
4243 curproxy->uri_auth = NULL; /* we must detach from the default config */
4244
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004245 if (!*args[1]) {
4246 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02004247 } else if (!strcmp(args[1], "admin")) {
4248 struct stats_admin_rule *rule;
4249
4250 if (curproxy == &defproxy) {
4251 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
4252 err_code |= ERR_ALERT | ERR_FATAL;
4253 goto out;
4254 }
4255
4256 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4257 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4258 err_code |= ERR_ALERT | ERR_ABORT;
4259 goto out;
4260 }
4261
4262 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4263 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4264 file, linenum, args[0], args[1]);
4265 err_code |= ERR_ALERT | ERR_FATAL;
4266 goto out;
4267 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004268 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4269 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
4270 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02004271 err_code |= ERR_ALERT | ERR_FATAL;
4272 goto out;
4273 }
4274
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004275 err_code |= warnif_cond_conflicts(cond,
4276 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4277 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02004278
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004279 rule = calloc(1, sizeof(*rule));
Cyril Bonté474be412010-10-12 00:14:36 +02004280 rule->cond = cond;
4281 LIST_INIT(&rule->list);
4282 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004283 } else if (!strcmp(args[1], "uri")) {
4284 if (*(args[2]) == 0) {
4285 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004286 err_code |= ERR_ALERT | ERR_FATAL;
4287 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004288 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
4289 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004290 err_code |= ERR_ALERT | ERR_ABORT;
4291 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004292 }
4293 } else if (!strcmp(args[1], "realm")) {
4294 if (*(args[2]) == 0) {
4295 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004296 err_code |= ERR_ALERT | ERR_FATAL;
4297 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004298 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
4299 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004300 err_code |= ERR_ALERT | ERR_ABORT;
4301 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004302 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02004303 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004304 unsigned interval;
4305
4306 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
4307 if (err) {
4308 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
4309 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004310 err_code |= ERR_ALERT | ERR_FATAL;
4311 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004312 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
4313 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004314 err_code |= ERR_ALERT | ERR_ABORT;
4315 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004316 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004317 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004318 struct act_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004319
4320 if (curproxy == &defproxy) {
4321 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4322 err_code |= ERR_ALERT | ERR_FATAL;
4323 goto out;
4324 }
4325
4326 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4327 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4328 err_code |= ERR_ALERT | ERR_ABORT;
4329 goto out;
4330 }
4331
Willy Tarreauff011f22011-01-06 17:51:27 +01004332 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004333 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct act_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004334 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
4335 file, linenum, args[0]);
4336 err_code |= ERR_WARN;
4337 }
4338
Willy Tarreauff011f22011-01-06 17:51:27 +01004339 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004340
Willy Tarreauff011f22011-01-06 17:51:27 +01004341 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004342 err_code |= ERR_ALERT | ERR_ABORT;
4343 goto out;
4344 }
4345
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004346 err_code |= warnif_cond_conflicts(rule->cond,
4347 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4348 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01004349 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004350
Willy Tarreaubaaee002006-06-26 02:48:02 +02004351 } else if (!strcmp(args[1], "auth")) {
4352 if (*(args[2]) == 0) {
4353 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004354 err_code |= ERR_ALERT | ERR_FATAL;
4355 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004356 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
4357 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004358 err_code |= ERR_ALERT | ERR_ABORT;
4359 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004360 }
4361 } else if (!strcmp(args[1], "scope")) {
4362 if (*(args[2]) == 0) {
4363 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004364 err_code |= ERR_ALERT | ERR_FATAL;
4365 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004366 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
4367 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004368 err_code |= ERR_ALERT | ERR_ABORT;
4369 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004370 }
4371 } else if (!strcmp(args[1], "enable")) {
4372 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4373 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004374 err_code |= ERR_ALERT | ERR_ABORT;
4375 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004376 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004377 } else if (!strcmp(args[1], "hide-version")) {
4378 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
4379 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004380 err_code |= ERR_ALERT | ERR_ABORT;
4381 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004382 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01004383 } else if (!strcmp(args[1], "show-legends")) {
4384 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
4385 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4386 err_code |= ERR_ALERT | ERR_ABORT;
4387 goto out;
4388 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004389 } else if (!strcmp(args[1], "show-node")) {
4390
4391 if (*args[2]) {
4392 int i;
4393 char c;
4394
4395 for (i=0; args[2][i]; i++) {
4396 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01004397 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
4398 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004399 break;
4400 }
4401
4402 if (!i || args[2][i]) {
4403 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
4404 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
4405 file, linenum, args[0], args[1]);
4406 err_code |= ERR_ALERT | ERR_FATAL;
4407 goto out;
4408 }
4409 }
4410
4411 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
4412 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4413 err_code |= ERR_ALERT | ERR_ABORT;
4414 goto out;
4415 }
4416 } else if (!strcmp(args[1], "show-desc")) {
4417 char *desc = NULL;
4418
4419 if (*args[2]) {
4420 int i, len=0;
4421 char *d;
4422
Willy Tarreau348acfe2014-04-14 15:00:39 +02004423 for (i = 2; *args[i]; i++)
4424 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004425
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004426 desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004427
Willy Tarreau348acfe2014-04-14 15:00:39 +02004428 d += snprintf(d, desc + len - d, "%s", args[2]);
4429 for (i = 3; *args[i]; i++)
4430 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004431 }
4432
4433 if (!*args[2] && !global.desc)
4434 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
4435 file, linenum, args[1]);
4436 else {
4437 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
4438 free(desc);
4439 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4440 err_code |= ERR_ALERT | ERR_ABORT;
4441 goto out;
4442 }
4443 free(desc);
4444 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004445 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004446stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02004447 Alert("parsing [%s:%d]: %s '%s', expects 'admin', 'uri', 'realm', 'auth', 'scope', 'enable', 'hide-version', 'show-node', 'show-desc' or 'show-legends'.\n",
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004448 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004449 err_code |= ERR_ALERT | ERR_FATAL;
4450 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004451 }
4452 }
4453 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004454 int optnum;
4455
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004456 if (*(args[1]) == '\0') {
4457 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
4458 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004459 err_code |= ERR_ALERT | ERR_FATAL;
4460 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004461 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01004462
4463 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
4464 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004465 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
4466 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4467 file, linenum, cfg_opts[optnum].name);
4468 err_code |= ERR_ALERT | ERR_FATAL;
4469 goto out;
4470 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004471 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4472 goto out;
4473
Willy Tarreau93893792009-07-23 13:19:11 +02004474 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
4475 err_code |= ERR_WARN;
4476 goto out;
4477 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004478
Willy Tarreau3842f002009-06-14 11:39:52 +02004479 curproxy->no_options &= ~cfg_opts[optnum].val;
4480 curproxy->options &= ~cfg_opts[optnum].val;
4481
4482 switch (kwm) {
4483 case KWM_STD:
4484 curproxy->options |= cfg_opts[optnum].val;
4485 break;
4486 case KWM_NO:
4487 curproxy->no_options |= cfg_opts[optnum].val;
4488 break;
4489 case KWM_DEF: /* already cleared */
4490 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004491 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004492
Willy Tarreau93893792009-07-23 13:19:11 +02004493 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004494 }
4495 }
4496
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004497 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
4498 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004499 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
4500 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4501 file, linenum, cfg_opts2[optnum].name);
4502 err_code |= ERR_ALERT | ERR_FATAL;
4503 goto out;
4504 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004505 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4506 goto out;
Willy Tarreau93893792009-07-23 13:19:11 +02004507 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4508 err_code |= ERR_WARN;
4509 goto out;
4510 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004511
Willy Tarreau3842f002009-06-14 11:39:52 +02004512 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4513 curproxy->options2 &= ~cfg_opts2[optnum].val;
4514
4515 switch (kwm) {
4516 case KWM_STD:
4517 curproxy->options2 |= cfg_opts2[optnum].val;
4518 break;
4519 case KWM_NO:
4520 curproxy->no_options2 |= cfg_opts2[optnum].val;
4521 break;
4522 case KWM_DEF: /* already cleared */
4523 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004524 }
Willy Tarreau93893792009-07-23 13:19:11 +02004525 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004526 }
4527 }
4528
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004529 /* HTTP options override each other. They can be cancelled using
4530 * "no option xxx" which only switches to default mode if the mode
4531 * was this one (useful for cancelling options set in defaults
4532 * sections).
4533 */
4534 if (strcmp(args[1], "httpclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004535 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4536 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004537 if (kwm == KWM_STD) {
4538 curproxy->options &= ~PR_O_HTTP_MODE;
4539 curproxy->options |= PR_O_HTTP_PCL;
4540 goto out;
4541 }
4542 else if (kwm == KWM_NO) {
4543 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4544 curproxy->options &= ~PR_O_HTTP_MODE;
4545 goto out;
4546 }
4547 }
4548 else if (strcmp(args[1], "forceclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004549 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4550 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004551 if (kwm == KWM_STD) {
4552 curproxy->options &= ~PR_O_HTTP_MODE;
4553 curproxy->options |= PR_O_HTTP_FCL;
4554 goto out;
4555 }
4556 else if (kwm == KWM_NO) {
4557 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4558 curproxy->options &= ~PR_O_HTTP_MODE;
4559 goto out;
4560 }
4561 }
4562 else if (strcmp(args[1], "http-server-close") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004563 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4564 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004565 if (kwm == KWM_STD) {
4566 curproxy->options &= ~PR_O_HTTP_MODE;
4567 curproxy->options |= PR_O_HTTP_SCL;
4568 goto out;
4569 }
4570 else if (kwm == KWM_NO) {
4571 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4572 curproxy->options &= ~PR_O_HTTP_MODE;
4573 goto out;
4574 }
4575 }
4576 else if (strcmp(args[1], "http-keep-alive") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004577 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4578 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004579 if (kwm == KWM_STD) {
4580 curproxy->options &= ~PR_O_HTTP_MODE;
4581 curproxy->options |= PR_O_HTTP_KAL;
4582 goto out;
4583 }
4584 else if (kwm == KWM_NO) {
4585 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4586 curproxy->options &= ~PR_O_HTTP_MODE;
4587 goto out;
4588 }
4589 }
4590 else if (strcmp(args[1], "http-tunnel") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004591 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4592 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004593 if (kwm == KWM_STD) {
4594 curproxy->options &= ~PR_O_HTTP_MODE;
4595 curproxy->options |= PR_O_HTTP_TUN;
4596 goto out;
4597 }
4598 else if (kwm == KWM_NO) {
4599 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4600 curproxy->options &= ~PR_O_HTTP_MODE;
4601 goto out;
4602 }
4603 }
4604
Joseph Lynch726ab712015-05-11 23:25:34 -07004605 /* Redispatch can take an integer argument that control when the
4606 * resispatch occurs. All values are relative to the retries option.
4607 * This can be cancelled using "no option xxx".
4608 */
4609 if (strcmp(args[1], "redispatch") == 0) {
4610 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
4611 err_code |= ERR_WARN;
4612 goto out;
4613 }
4614
4615 curproxy->no_options &= ~PR_O_REDISP;
4616 curproxy->options &= ~PR_O_REDISP;
4617
4618 switch (kwm) {
4619 case KWM_STD:
4620 curproxy->options |= PR_O_REDISP;
4621 curproxy->redispatch_after = -1;
4622 if(*args[2]) {
4623 curproxy->redispatch_after = atol(args[2]);
4624 }
4625 break;
4626 case KWM_NO:
4627 curproxy->no_options |= PR_O_REDISP;
4628 curproxy->redispatch_after = 0;
4629 break;
4630 case KWM_DEF: /* already cleared */
4631 break;
4632 }
4633 goto out;
4634 }
4635
Willy Tarreau3842f002009-06-14 11:39:52 +02004636 if (kwm != KWM_STD) {
4637 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004638 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004639 err_code |= ERR_ALERT | ERR_FATAL;
4640 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004641 }
4642
Emeric Brun3a058f32009-06-30 18:26:00 +02004643 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004644 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004645 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004646 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004647 if (*(args[2]) != '\0') {
4648 if (!strcmp(args[2], "clf")) {
4649 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004650 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004651 } else {
William Lallemand77063bc2015-05-28 18:02:48 +02004652 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004653 err_code |= ERR_ALERT | ERR_FATAL;
4654 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004655 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004656 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
4657 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004658 }
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02004659 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
4660 char *oldlogformat = "log-format";
4661 char *clflogformat = "";
4662
4663 if (curproxy->conf.logformat_string == default_http_log_format)
4664 oldlogformat = "option httplog";
4665 else if (curproxy->conf.logformat_string == default_tcp_log_format)
4666 oldlogformat = "option tcplog";
4667 else if (curproxy->conf.logformat_string == clf_http_log_format)
4668 oldlogformat = "option httplog clf";
4669 if (logformat == clf_http_log_format)
4670 clflogformat = " clf";
4671 Warning("parsing [%s:%d]: 'option httplog%s' overrides previous '%s' in 'defaults' section.\n",
4672 file, linenum, clflogformat, oldlogformat);
4673 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004674 if (curproxy->conf.logformat_string != default_http_log_format &&
4675 curproxy->conf.logformat_string != default_tcp_log_format &&
4676 curproxy->conf.logformat_string != clf_http_log_format)
4677 free(curproxy->conf.logformat_string);
4678 curproxy->conf.logformat_string = logformat;
4679
4680 free(curproxy->conf.lfs_file);
4681 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4682 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004683 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004684 else if (!strcmp(args[1], "tcplog")) {
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02004685 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
4686 char *oldlogformat = "log-format";
4687
4688 if (curproxy->conf.logformat_string == default_http_log_format)
4689 oldlogformat = "option httplog";
4690 else if (curproxy->conf.logformat_string == default_tcp_log_format)
4691 oldlogformat = "option tcplog";
4692 else if (curproxy->conf.logformat_string == clf_http_log_format)
4693 oldlogformat = "option httplog clf";
4694 Warning("parsing [%s:%d]: 'option tcplog' overrides previous '%s' in 'defaults' section.\n",
4695 file, linenum, oldlogformat);
4696 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004697 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004698 if (curproxy->conf.logformat_string != default_http_log_format &&
4699 curproxy->conf.logformat_string != default_tcp_log_format &&
4700 curproxy->conf.logformat_string != clf_http_log_format)
4701 free(curproxy->conf.logformat_string);
4702 curproxy->conf.logformat_string = default_tcp_log_format;
4703
4704 free(curproxy->conf.lfs_file);
4705 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4706 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemanddf1425a2015-04-28 20:17:49 +02004707
4708 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4709 goto out;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004710 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004711 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004712 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004713 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004714 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004715
William Lallemanddf1425a2015-04-28 20:17:49 +02004716 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4717 goto out;
4718
Willy Tarreau13943ab2006-12-31 00:24:10 +01004719 if (curproxy->cap & PR_CAP_FE)
4720 curproxy->options |= PR_O_TCP_CLI_KA;
4721 if (curproxy->cap & PR_CAP_BE)
4722 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004723 }
4724 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004725 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004726 err_code |= ERR_WARN;
4727
Willy Tarreaubaaee002006-06-26 02:48:02 +02004728 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004729 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004730 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004731 curproxy->options2 &= ~PR_O2_CHK_ANY;
4732 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004733 if (!*args[2]) { /* no argument */
4734 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4735 curproxy->check_len = strlen(DEF_CHECK_REQ);
4736 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004737 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004738 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004739 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004740 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004741 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004742 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004743 if (*args[4])
4744 reqlen += strlen(args[4]);
4745 else
4746 reqlen += strlen("HTTP/1.0");
4747
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004748 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004749 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004750 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004751 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004752 if (alertif_too_many_args_idx(3, 1, file, linenum, args, &err_code))
4753 goto out;
Willy Tarreauf3c69202006-07-09 16:42:34 +02004754 }
4755 else if (!strcmp(args[1], "ssl-hello-chk")) {
4756 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004757 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004758 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004759
Willy Tarreaua534fea2008-08-03 12:19:50 +02004760 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004761 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004762 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004763 curproxy->options2 |= PR_O2_SSL3_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004764
4765 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4766 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004767 }
Willy Tarreau23677902007-05-08 23:50:35 +02004768 else if (!strcmp(args[1], "smtpchk")) {
4769 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004770 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004771 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004772 curproxy->options2 &= ~PR_O2_CHK_ANY;
4773 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004774
4775 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4776 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4777 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4778 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4779 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4780 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004781 curproxy->check_req = malloc(reqlen);
Willy Tarreau23677902007-05-08 23:50:35 +02004782 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4783 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4784 } else {
4785 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4786 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4787 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4788 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4789 }
4790 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004791 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4792 goto out;
Willy Tarreau23677902007-05-08 23:50:35 +02004793 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004794 else if (!strcmp(args[1], "pgsql-check")) {
4795 /* use PostgreSQL request to check servers' health */
4796 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4797 err_code |= ERR_WARN;
4798
4799 free(curproxy->check_req);
4800 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004801 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004802 curproxy->options2 |= PR_O2_PGSQL_CHK;
4803
4804 if (*(args[2])) {
4805 int cur_arg = 2;
4806
4807 while (*(args[cur_arg])) {
4808 if (strcmp(args[cur_arg], "user") == 0) {
4809 char * packet;
4810 uint32_t packet_len;
4811 uint32_t pv;
4812
4813 /* suboption header - needs additional argument for it */
4814 if (*(args[cur_arg+1]) == 0) {
4815 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4816 file, linenum, args[0], args[1], args[cur_arg]);
4817 err_code |= ERR_ALERT | ERR_FATAL;
4818 goto out;
4819 }
4820
4821 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4822 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4823 pv = htonl(0x30000); /* protocol version 3.0 */
4824
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004825 packet = calloc(1, packet_len);
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004826
4827 memcpy(packet + 4, &pv, 4);
4828
4829 /* copy "user" */
4830 memcpy(packet + 8, "user", 4);
4831
4832 /* copy username */
4833 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4834
4835 free(curproxy->check_req);
4836 curproxy->check_req = packet;
4837 curproxy->check_len = packet_len;
4838
4839 packet_len = htonl(packet_len);
4840 memcpy(packet, &packet_len, 4);
4841 cur_arg += 2;
4842 } else {
4843 /* unknown suboption - catchall */
4844 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4845 file, linenum, args[0], args[1]);
4846 err_code |= ERR_ALERT | ERR_FATAL;
4847 goto out;
4848 }
4849 } /* end while loop */
4850 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004851 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4852 goto out;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004853 }
4854
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004855 else if (!strcmp(args[1], "redis-check")) {
4856 /* use REDIS PING request to check servers' health */
4857 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4858 err_code |= ERR_WARN;
4859
4860 free(curproxy->check_req);
4861 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004862 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004863 curproxy->options2 |= PR_O2_REDIS_CHK;
4864
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004865 curproxy->check_req = malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004866 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4867 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004868
4869 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4870 goto out;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004871 }
4872
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004873 else if (!strcmp(args[1], "mysql-check")) {
4874 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004875 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4876 err_code |= ERR_WARN;
4877
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004878 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004879 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004880 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004881 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004882
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004883 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004884 * const char mysql40_client_auth_pkt[] = {
4885 * "\x0e\x00\x00" // packet length
4886 * "\x01" // packet number
4887 * "\x00\x00" // client capabilities
4888 * "\x00\x00\x01" // max packet
4889 * "haproxy\x00" // username (null terminated string)
4890 * "\x00" // filler (always 0x00)
4891 * "\x01\x00\x00" // packet length
4892 * "\x00" // packet number
4893 * "\x01" // COM_QUIT command
4894 * };
4895 */
4896
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004897 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4898 * const char mysql41_client_auth_pkt[] = {
4899 * "\x0e\x00\x00\" // packet length
4900 * "\x01" // packet number
4901 * "\x00\x00\x00\x00" // client capabilities
4902 * "\x00\x00\x00\x01" // max packet
4903 * "\x21" // character set (UTF-8)
4904 * char[23] // All zeroes
4905 * "haproxy\x00" // username (null terminated string)
4906 * "\x00" // filler (always 0x00)
4907 * "\x01\x00\x00" // packet length
4908 * "\x00" // packet number
4909 * "\x01" // COM_QUIT command
4910 * };
4911 */
4912
4913
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004914 if (*(args[2])) {
4915 int cur_arg = 2;
4916
4917 while (*(args[cur_arg])) {
4918 if (strcmp(args[cur_arg], "user") == 0) {
4919 char *mysqluser;
4920 int packetlen, reqlen, userlen;
4921
4922 /* suboption header - needs additional argument for it */
4923 if (*(args[cur_arg+1]) == 0) {
4924 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4925 file, linenum, args[0], args[1], args[cur_arg]);
4926 err_code |= ERR_ALERT | ERR_FATAL;
4927 goto out;
4928 }
4929 mysqluser = args[cur_arg + 1];
4930 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004931
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004932 if (*(args[cur_arg+2])) {
4933 if (!strcmp(args[cur_arg+2], "post-41")) {
4934 packetlen = userlen + 7 + 27;
4935 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004936
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004937 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004938 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004939 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004940
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004941 snprintf(curproxy->check_req, 4, "%c%c%c",
4942 ((unsigned char) packetlen & 0xff),
4943 ((unsigned char) (packetlen >> 8) & 0xff),
4944 ((unsigned char) (packetlen >> 16) & 0xff));
4945
4946 curproxy->check_req[3] = 1;
4947 curproxy->check_req[5] = 130;
4948 curproxy->check_req[11] = 1;
4949 curproxy->check_req[12] = 33;
4950 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4951 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4952 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4953 cur_arg += 3;
4954 } else {
4955 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4956 err_code |= ERR_ALERT | ERR_FATAL;
4957 goto out;
4958 }
4959 } else {
4960 packetlen = userlen + 7;
4961 reqlen = packetlen + 9;
4962
4963 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004964 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004965 curproxy->check_len = reqlen;
4966
4967 snprintf(curproxy->check_req, 4, "%c%c%c",
4968 ((unsigned char) packetlen & 0xff),
4969 ((unsigned char) (packetlen >> 8) & 0xff),
4970 ((unsigned char) (packetlen >> 16) & 0xff));
4971
4972 curproxy->check_req[3] = 1;
4973 curproxy->check_req[5] = 128;
4974 curproxy->check_req[8] = 1;
4975 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4976 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4977 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4978 cur_arg += 2;
4979 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004980 } else {
4981 /* unknown suboption - catchall */
4982 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4983 file, linenum, args[0], args[1]);
4984 err_code |= ERR_ALERT | ERR_FATAL;
4985 goto out;
4986 }
4987 } /* end while loop */
4988 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004989 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004990 else if (!strcmp(args[1], "ldap-check")) {
4991 /* use LDAP request to check servers' health */
4992 free(curproxy->check_req);
4993 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004994 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004995 curproxy->options2 |= PR_O2_LDAP_CHK;
4996
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004997 curproxy->check_req = malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004998 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
4999 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02005000 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5001 goto out;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005002 }
Christopher Fauletba7bc162016-11-07 21:07:38 +01005003 else if (!strcmp(args[1], "spop-check")) {
5004 if (curproxy == &defproxy) {
5005 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n",
5006 file, linenum, args[0], args[1]);
5007 err_code |= ERR_ALERT | ERR_FATAL;
5008 goto out;
5009 }
5010 if (curproxy->cap & PR_CAP_FE) {
5011 Alert("parsing [%s:%d] : '%s %s' not allowed in 'frontend' and 'listen' sections.\n",
5012 file, linenum, args[0], args[1]);
5013 err_code |= ERR_ALERT | ERR_FATAL;
5014 goto out;
5015 }
5016
5017 /* use SPOE request to check servers' health */
5018 free(curproxy->check_req);
5019 curproxy->check_req = NULL;
5020 curproxy->options2 &= ~PR_O2_CHK_ANY;
5021 curproxy->options2 |= PR_O2_SPOP_CHK;
5022
Christopher Faulet8ef75252017-02-20 22:56:03 +01005023 if (spoe_prepare_healthcheck_request(&curproxy->check_req, &curproxy->check_len)) {
Christopher Fauletba7bc162016-11-07 21:07:38 +01005024 Alert("parsing [%s:%d] : failed to prepare SPOP healthcheck request.\n", file, linenum);
5025 err_code |= ERR_ALERT | ERR_FATAL;
5026 goto out;
5027 }
5028 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5029 goto out;
5030 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005031 else if (!strcmp(args[1], "tcp-check")) {
5032 /* use raw TCPCHK send/expect to check servers' health */
5033 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
5034 err_code |= ERR_WARN;
5035
5036 free(curproxy->check_req);
5037 curproxy->check_req = NULL;
5038 curproxy->options2 &= ~PR_O2_CHK_ANY;
5039 curproxy->options2 |= PR_O2_TCPCHK_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005040 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5041 goto out;
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005042 }
Simon Horman98637e52014-06-20 12:30:16 +09005043 else if (!strcmp(args[1], "external-check")) {
5044 /* excute an external command to check servers' health */
5045 free(curproxy->check_req);
5046 curproxy->check_req = NULL;
5047 curproxy->options2 &= ~PR_O2_CHK_ANY;
5048 curproxy->options2 |= PR_O2_EXT_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005049 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5050 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09005051 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005052 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005053 int cur_arg;
5054
5055 /* insert x-forwarded-for field, but not for the IP address listed as an except.
5056 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005057 */
Ross Westaf72a1d2008-08-03 10:51:45 +02005058
Willy Tarreau87cf5142011-08-19 22:57:24 +02005059 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02005060
5061 free(curproxy->fwdfor_hdr_name);
5062 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
5063 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
5064
5065 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
5066 cur_arg = 2;
5067 while (*(args[cur_arg])) {
5068 if (!strcmp(args[cur_arg], "except")) {
5069 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005070 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005071 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5072 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005073 err_code |= ERR_ALERT | ERR_FATAL;
5074 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005075 }
5076 /* flush useless bits */
5077 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02005078 cur_arg += 2;
5079 } else if (!strcmp(args[cur_arg], "header")) {
5080 /* suboption header - needs additional argument for it */
5081 if (*(args[cur_arg+1]) == 0) {
5082 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5083 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005084 err_code |= ERR_ALERT | ERR_FATAL;
5085 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02005086 }
5087 free(curproxy->fwdfor_hdr_name);
5088 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
5089 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
5090 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02005091 } else if (!strcmp(args[cur_arg], "if-none")) {
5092 curproxy->options &= ~PR_O_FF_ALWAYS;
5093 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005094 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02005095 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02005096 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02005097 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005098 err_code |= ERR_ALERT | ERR_FATAL;
5099 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005100 }
Ross Westaf72a1d2008-08-03 10:51:45 +02005101 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005102 }
Maik Broemme2850cb42009-04-17 18:53:21 +02005103 else if (!strcmp(args[1], "originalto")) {
5104 int cur_arg;
5105
5106 /* insert x-original-to field, but not for the IP address listed as an except.
5107 * set default options (ie: bitfield, header name, etc)
5108 */
5109
5110 curproxy->options |= PR_O_ORGTO;
5111
5112 free(curproxy->orgto_hdr_name);
5113 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
5114 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
5115
Willy Tarreau87cf5142011-08-19 22:57:24 +02005116 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02005117 cur_arg = 2;
5118 while (*(args[cur_arg])) {
5119 if (!strcmp(args[cur_arg], "except")) {
5120 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005121 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_to, &curproxy->except_mask_to)) {
Maik Broemme2850cb42009-04-17 18:53:21 +02005122 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5123 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005124 err_code |= ERR_ALERT | ERR_FATAL;
5125 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005126 }
5127 /* flush useless bits */
5128 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
5129 cur_arg += 2;
5130 } else if (!strcmp(args[cur_arg], "header")) {
5131 /* suboption header - needs additional argument for it */
5132 if (*(args[cur_arg+1]) == 0) {
5133 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5134 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005135 err_code |= ERR_ALERT | ERR_FATAL;
5136 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005137 }
5138 free(curproxy->orgto_hdr_name);
5139 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
5140 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
5141 cur_arg += 2;
5142 } else {
5143 /* unknown suboption - catchall */
5144 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
5145 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005146 err_code |= ERR_ALERT | ERR_FATAL;
5147 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005148 }
5149 } /* end while loop */
5150 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005151 else {
5152 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005153 err_code |= ERR_ALERT | ERR_FATAL;
5154 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005155 }
Willy Tarreau93893792009-07-23 13:19:11 +02005156 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005157 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005158 else if (!strcmp(args[0], "default_backend")) {
5159 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005160 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005161
5162 if (*(args[1]) == 0) {
5163 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005164 err_code |= ERR_ALERT | ERR_FATAL;
5165 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005166 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005167 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005168 curproxy->defbe.name = strdup(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005169
5170 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5171 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005172 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005173 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01005174 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005175 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005176
Willy Tarreaua3c504c2014-04-28 22:37:32 +02005177 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
5178 Warning("parsing [%s:%d]: keyword '%s' is deprecated in favor of 'option redispatch', and will not be supported by future versions.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005179 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005180 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005181 /* enable reconnections to dispatch */
5182 curproxy->options |= PR_O_REDISP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005183
5184 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5185 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005186 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005187 else if (!strcmp(args[0], "http-reuse")) {
5188 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5189 err_code |= ERR_WARN;
5190
5191 if (strcmp(args[1], "never") == 0) {
5192 /* enable a graceful server shutdown on an HTTP 404 response */
5193 curproxy->options &= ~PR_O_REUSE_MASK;
5194 curproxy->options |= PR_O_REUSE_NEVR;
5195 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5196 goto out;
5197 }
Willy Tarreau161d45f2015-08-05 16:02:46 +02005198 else if (strcmp(args[1], "safe") == 0) {
5199 /* enable a graceful server shutdown on an HTTP 404 response */
5200 curproxy->options &= ~PR_O_REUSE_MASK;
5201 curproxy->options |= PR_O_REUSE_SAFE;
5202 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5203 goto out;
5204 }
Willy Tarreau449d74a2015-08-05 17:16:33 +02005205 else if (strcmp(args[1], "aggressive") == 0) {
5206 curproxy->options &= ~PR_O_REUSE_MASK;
5207 curproxy->options |= PR_O_REUSE_AGGR;
5208 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5209 goto out;
5210 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005211 else if (strcmp(args[1], "always") == 0) {
5212 /* enable a graceful server shutdown on an HTTP 404 response */
5213 curproxy->options &= ~PR_O_REUSE_MASK;
5214 curproxy->options |= PR_O_REUSE_ALWS;
5215 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5216 goto out;
5217 }
5218 else {
Willy Tarreau449d74a2015-08-05 17:16:33 +02005219 Alert("parsing [%s:%d] : '%s' only supports 'never', 'safe', 'aggressive', 'always'.\n", file, linenum, args[0]);
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005220 err_code |= ERR_ALERT | ERR_FATAL;
5221 goto out;
5222 }
5223 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005224 else if (!strcmp(args[0], "http-check")) {
5225 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005226 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01005227
5228 if (strcmp(args[1], "disable-on-404") == 0) {
5229 /* enable a graceful server shutdown on an HTTP 404 response */
5230 curproxy->options |= PR_O_DISABLE404;
William Lallemanddf1425a2015-04-28 20:17:49 +02005231 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5232 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005233 }
Willy Tarreauef781042010-01-27 11:53:01 +01005234 else if (strcmp(args[1], "send-state") == 0) {
5235 /* enable emission of the apparent state of a server in HTTP checks */
5236 curproxy->options2 |= PR_O2_CHK_SNDST;
William Lallemanddf1425a2015-04-28 20:17:49 +02005237 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5238 goto out;
Willy Tarreauef781042010-01-27 11:53:01 +01005239 }
Willy Tarreaubd741542010-03-16 18:46:54 +01005240 else if (strcmp(args[1], "expect") == 0) {
5241 const char *ptr_arg;
5242 int cur_arg;
5243
5244 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5245 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5246 err_code |= ERR_ALERT | ERR_FATAL;
5247 goto out;
5248 }
5249
5250 cur_arg = 2;
5251 /* consider exclamation marks, sole or at the beginning of a word */
5252 while (*(ptr_arg = args[cur_arg])) {
5253 while (*ptr_arg == '!') {
5254 curproxy->options2 ^= PR_O2_EXP_INV;
5255 ptr_arg++;
5256 }
5257 if (*ptr_arg)
5258 break;
5259 cur_arg++;
5260 }
5261 /* now ptr_arg points to the beginning of a word past any possible
5262 * exclamation mark, and cur_arg is the argument which holds this word.
5263 */
5264 if (strcmp(ptr_arg, "status") == 0) {
5265 if (!*(args[cur_arg + 1])) {
5266 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5267 file, linenum, args[0], args[1], ptr_arg);
5268 err_code |= ERR_ALERT | ERR_FATAL;
5269 goto out;
5270 }
5271 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005272 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005273 curproxy->expect_str = strdup(args[cur_arg + 1]);
5274 }
5275 else if (strcmp(ptr_arg, "string") == 0) {
5276 if (!*(args[cur_arg + 1])) {
5277 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5278 file, linenum, args[0], args[1], ptr_arg);
5279 err_code |= ERR_ALERT | ERR_FATAL;
5280 goto out;
5281 }
5282 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005283 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005284 curproxy->expect_str = strdup(args[cur_arg + 1]);
5285 }
5286 else if (strcmp(ptr_arg, "rstatus") == 0) {
5287 if (!*(args[cur_arg + 1])) {
5288 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5289 file, linenum, args[0], args[1], ptr_arg);
5290 err_code |= ERR_ALERT | ERR_FATAL;
5291 goto out;
5292 }
5293 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005294 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005295 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005296 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005297 free(curproxy->expect_regex);
5298 curproxy->expect_regex = NULL;
5299 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005300 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005301 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5302 error = NULL;
5303 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5304 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5305 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5306 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005307 err_code |= ERR_ALERT | ERR_FATAL;
5308 goto out;
5309 }
5310 }
5311 else if (strcmp(ptr_arg, "rstring") == 0) {
5312 if (!*(args[cur_arg + 1])) {
5313 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5314 file, linenum, args[0], args[1], ptr_arg);
5315 err_code |= ERR_ALERT | ERR_FATAL;
5316 goto out;
5317 }
5318 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005319 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005320 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005321 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005322 free(curproxy->expect_regex);
5323 curproxy->expect_regex = NULL;
5324 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005325 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005326 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5327 error = NULL;
5328 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5329 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5330 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5331 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005332 err_code |= ERR_ALERT | ERR_FATAL;
5333 goto out;
5334 }
5335 }
5336 else {
5337 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
5338 file, linenum, args[0], args[1], ptr_arg);
5339 err_code |= ERR_ALERT | ERR_FATAL;
5340 goto out;
5341 }
5342 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005343 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005344 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404', 'send-state', 'expect'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005345 err_code |= ERR_ALERT | ERR_FATAL;
5346 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005347 }
5348 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005349 else if (!strcmp(args[0], "tcp-check")) {
5350 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5351 err_code |= ERR_WARN;
5352
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005353 if (strcmp(args[1], "comment") == 0) {
5354 int cur_arg;
5355 struct tcpcheck_rule *tcpcheck;
5356
5357 cur_arg = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005358 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005359 tcpcheck->action = TCPCHK_ACT_COMMENT;
5360
5361 if (!*args[cur_arg + 1]) {
5362 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5363 file, linenum, args[cur_arg]);
5364 err_code |= ERR_ALERT | ERR_FATAL;
5365 goto out;
5366 }
5367
5368 tcpcheck->comment = strdup(args[cur_arg + 1]);
5369
5370 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
William Lallemanddf1425a2015-04-28 20:17:49 +02005371 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
5372 goto out;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005373 }
5374 else if (strcmp(args[1], "connect") == 0) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005375 const char *ptr_arg;
5376 int cur_arg;
5377 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005378
5379 /* check if first rule is also a 'connect' action */
Willy Tarreau5581c272015-05-13 12:24:53 +02005380 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
5381 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
5382 tcpcheck->action == TCPCHK_ACT_COMMENT) {
5383 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
5384 }
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005385
Willy Tarreau5581c272015-05-13 12:24:53 +02005386 if (&tcpcheck->list != &curproxy->tcpcheck_rules
5387 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
5388 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
5389 file, linenum);
5390 err_code |= ERR_ALERT | ERR_FATAL;
5391 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005392 }
5393
5394 cur_arg = 2;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005395 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005396 tcpcheck->action = TCPCHK_ACT_CONNECT;
5397
5398 /* parsing each parameters to fill up the rule */
5399 while (*(ptr_arg = args[cur_arg])) {
5400 /* tcp port */
5401 if (strcmp(args[cur_arg], "port") == 0) {
5402 if ( (atol(args[cur_arg + 1]) > 65535) ||
5403 (atol(args[cur_arg + 1]) < 1) ){
5404 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
5405 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
5406 err_code |= ERR_ALERT | ERR_FATAL;
5407 goto out;
5408 }
5409 tcpcheck->port = atol(args[cur_arg + 1]);
5410 cur_arg += 2;
5411 }
5412 /* send proxy protocol */
5413 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
5414 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
5415 cur_arg++;
5416 }
5417#ifdef USE_OPENSSL
5418 else if (strcmp(args[cur_arg], "ssl") == 0) {
5419 curproxy->options |= PR_O_TCPCHK_SSL;
5420 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
5421 cur_arg++;
5422 }
5423#endif /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005424 /* comment for this tcpcheck line */
5425 else if (strcmp(args[cur_arg], "comment") == 0) {
5426 if (!*args[cur_arg + 1]) {
5427 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5428 file, linenum, args[cur_arg]);
5429 err_code |= ERR_ALERT | ERR_FATAL;
5430 goto out;
5431 }
5432 tcpcheck->comment = strdup(args[cur_arg + 1]);
5433 cur_arg += 2;
5434 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005435 else {
5436#ifdef USE_OPENSSL
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005437 Alert("parsing [%s:%d] : '%s %s' expects 'comment', 'port', 'send-proxy' or 'ssl' but got '%s' as argument.\n",
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005438#else /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005439 Alert("parsing [%s:%d] : '%s %s' expects 'comment', 'port', 'send-proxy' or but got '%s' as argument.\n",
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005440#endif /* USE_OPENSSL */
5441 file, linenum, args[0], args[1], args[cur_arg]);
5442 err_code |= ERR_ALERT | ERR_FATAL;
5443 goto out;
5444 }
5445
5446 }
5447
5448 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5449 }
5450 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005451 if (! *(args[2]) ) {
5452 /* SEND string expected */
5453 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
5454 file, linenum, args[0], args[1], args[2]);
5455 err_code |= ERR_ALERT | ERR_FATAL;
5456 goto out;
5457 } else {
5458 struct tcpcheck_rule *tcpcheck;
5459
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005460 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005461
5462 tcpcheck->action = TCPCHK_ACT_SEND;
5463 tcpcheck->string_len = strlen(args[2]);
5464 tcpcheck->string = strdup(args[2]);
5465 tcpcheck->expect_regex = NULL;
5466
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005467 /* comment for this tcpcheck line */
5468 if (strcmp(args[3], "comment") == 0) {
5469 if (!*args[4]) {
5470 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5471 file, linenum, args[3]);
5472 err_code |= ERR_ALERT | ERR_FATAL;
5473 goto out;
5474 }
5475 tcpcheck->comment = strdup(args[4]);
5476 }
5477
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005478 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5479 }
5480 }
5481 else if (strcmp(args[1], "send-binary") == 0) {
5482 if (! *(args[2]) ) {
5483 /* SEND binary string expected */
5484 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
5485 file, linenum, args[0], args[1], args[2]);
5486 err_code |= ERR_ALERT | ERR_FATAL;
5487 goto out;
5488 } else {
5489 struct tcpcheck_rule *tcpcheck;
5490 char *err = NULL;
5491
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005492 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005493
5494 tcpcheck->action = TCPCHK_ACT_SEND;
5495 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5496 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5497 file, linenum, args[0], args[1], args[2], err);
5498 err_code |= ERR_ALERT | ERR_FATAL;
5499 goto out;
5500 }
5501 tcpcheck->expect_regex = NULL;
5502
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005503 /* comment for this tcpcheck line */
5504 if (strcmp(args[3], "comment") == 0) {
5505 if (!*args[4]) {
5506 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5507 file, linenum, args[3]);
5508 err_code |= ERR_ALERT | ERR_FATAL;
5509 goto out;
5510 }
5511 tcpcheck->comment = strdup(args[4]);
5512 }
5513
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005514 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5515 }
5516 }
5517 else if (strcmp(args[1], "expect") == 0) {
5518 const char *ptr_arg;
5519 int cur_arg;
5520 int inverse = 0;
5521
5522 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5523 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5524 err_code |= ERR_ALERT | ERR_FATAL;
5525 goto out;
5526 }
5527
5528 cur_arg = 2;
5529 /* consider exclamation marks, sole or at the beginning of a word */
5530 while (*(ptr_arg = args[cur_arg])) {
5531 while (*ptr_arg == '!') {
5532 inverse = !inverse;
5533 ptr_arg++;
5534 }
5535 if (*ptr_arg)
5536 break;
5537 cur_arg++;
5538 }
5539 /* now ptr_arg points to the beginning of a word past any possible
5540 * exclamation mark, and cur_arg is the argument which holds this word.
5541 */
5542 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005543 struct tcpcheck_rule *tcpcheck;
5544 char *err = NULL;
5545
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005546 if (!*(args[cur_arg + 1])) {
5547 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
5548 file, linenum, args[0], args[1], ptr_arg);
5549 err_code |= ERR_ALERT | ERR_FATAL;
5550 goto out;
5551 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005552
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005553 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005554
5555 tcpcheck->action = TCPCHK_ACT_EXPECT;
5556 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5557 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5558 file, linenum, args[0], args[1], args[2], err);
5559 err_code |= ERR_ALERT | ERR_FATAL;
5560 goto out;
5561 }
5562 tcpcheck->expect_regex = NULL;
5563 tcpcheck->inverse = inverse;
5564
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005565 /* tcpcheck comment */
5566 cur_arg += 2;
5567 if (strcmp(args[cur_arg], "comment") == 0) {
5568 if (!*args[cur_arg + 1]) {
5569 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5570 file, linenum, args[cur_arg + 1]);
5571 err_code |= ERR_ALERT | ERR_FATAL;
5572 goto out;
5573 }
5574 tcpcheck->comment = strdup(args[cur_arg + 1]);
5575 }
5576
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005577 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5578 }
5579 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005580 struct tcpcheck_rule *tcpcheck;
5581
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005582 if (!*(args[cur_arg + 1])) {
5583 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5584 file, linenum, args[0], args[1], ptr_arg);
5585 err_code |= ERR_ALERT | ERR_FATAL;
5586 goto out;
5587 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005588
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005589 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005590
5591 tcpcheck->action = TCPCHK_ACT_EXPECT;
5592 tcpcheck->string_len = strlen(args[cur_arg + 1]);
5593 tcpcheck->string = strdup(args[cur_arg + 1]);
5594 tcpcheck->expect_regex = NULL;
5595 tcpcheck->inverse = inverse;
5596
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005597 /* tcpcheck comment */
5598 cur_arg += 2;
5599 if (strcmp(args[cur_arg], "comment") == 0) {
5600 if (!*args[cur_arg + 1]) {
5601 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5602 file, linenum, args[cur_arg + 1]);
5603 err_code |= ERR_ALERT | ERR_FATAL;
5604 goto out;
5605 }
5606 tcpcheck->comment = strdup(args[cur_arg + 1]);
5607 }
5608
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005609 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5610 }
5611 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005612 struct tcpcheck_rule *tcpcheck;
5613
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005614 if (!*(args[cur_arg + 1])) {
5615 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5616 file, linenum, args[0], args[1], ptr_arg);
5617 err_code |= ERR_ALERT | ERR_FATAL;
5618 goto out;
5619 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005620
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005621 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005622
5623 tcpcheck->action = TCPCHK_ACT_EXPECT;
5624 tcpcheck->string_len = 0;
5625 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005626 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
5627 error = NULL;
5628 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
5629 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5630 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5631 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005632 err_code |= ERR_ALERT | ERR_FATAL;
5633 goto out;
5634 }
5635 tcpcheck->inverse = inverse;
5636
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005637 /* tcpcheck comment */
5638 cur_arg += 2;
5639 if (strcmp(args[cur_arg], "comment") == 0) {
5640 if (!*args[cur_arg + 1]) {
5641 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5642 file, linenum, args[cur_arg + 1]);
5643 err_code |= ERR_ALERT | ERR_FATAL;
5644 goto out;
5645 }
5646 tcpcheck->comment = strdup(args[cur_arg + 1]);
5647 }
5648
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005649 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5650 }
5651 else {
5652 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
5653 file, linenum, args[0], args[1], ptr_arg);
5654 err_code |= ERR_ALERT | ERR_FATAL;
5655 goto out;
5656 }
5657 }
5658 else {
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005659 Alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005660 err_code |= ERR_ALERT | ERR_FATAL;
5661 goto out;
5662 }
5663 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01005664 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02005665 if (curproxy == &defproxy) {
5666 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005667 err_code |= ERR_ALERT | ERR_FATAL;
5668 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02005669 }
5670
Willy Tarreaub80c2302007-11-30 20:51:32 +01005671 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005672 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005673
5674 if (strcmp(args[1], "fail") == 0) {
5675 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01005676 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01005677 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
5678 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005679 err_code |= ERR_ALERT | ERR_FATAL;
5680 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005681 }
5682
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005683 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
5684 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
5685 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005686 err_code |= ERR_ALERT | ERR_FATAL;
5687 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005688 }
5689 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
5690 }
5691 else {
5692 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005693 err_code |= ERR_ALERT | ERR_FATAL;
5694 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005695 }
5696 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005697#ifdef TPROXY
5698 else if (!strcmp(args[0], "transparent")) {
5699 /* enable transparent proxy connections */
5700 curproxy->options |= PR_O_TRANSP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005701 if (alertif_too_many_args(0, file, linenum, args, &err_code))
5702 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005703 }
5704#endif
5705 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005706 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005707 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005708
Willy Tarreaubaaee002006-06-26 02:48:02 +02005709 if (*(args[1]) == 0) {
5710 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005711 err_code |= ERR_ALERT | ERR_FATAL;
5712 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005713 }
5714 curproxy->maxconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005715 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5716 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005717 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005718 else if (!strcmp(args[0], "backlog")) { /* backlog */
5719 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005720 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005721
5722 if (*(args[1]) == 0) {
5723 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005724 err_code |= ERR_ALERT | ERR_FATAL;
5725 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005726 }
5727 curproxy->backlog = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005728 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5729 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005730 }
Willy Tarreau86034312006-12-29 00:10:33 +01005731 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005732 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005733 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005734
Willy Tarreau86034312006-12-29 00:10:33 +01005735 if (*(args[1]) == 0) {
5736 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005737 err_code |= ERR_ALERT | ERR_FATAL;
5738 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005739 }
5740 curproxy->fullconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005741 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5742 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005743 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005744 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
5745 if (*(args[1]) == 0) {
5746 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005747 err_code |= ERR_ALERT | ERR_FATAL;
5748 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005749 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005750 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
5751 if (err) {
5752 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
5753 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02005754 err_code |= ERR_ALERT | ERR_FATAL;
5755 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005756 }
5757 curproxy->grace = val;
William Lallemanddf1425a2015-04-28 20:17:49 +02005758 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5759 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005760 }
5761 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01005762 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005763 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005764 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005765
Willy Tarreaubaaee002006-06-26 02:48:02 +02005766 if (curproxy == &defproxy) {
5767 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005768 err_code |= ERR_ALERT | ERR_FATAL;
5769 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005770 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005771 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005772 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005773
Willy Tarreau48ef4c92017-01-06 18:32:38 +01005774 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005775 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005776 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005777 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005778 goto out;
5779 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005780
5781 proto = protocol_by_family(sk->ss_family);
5782 if (!proto || !proto->connect) {
5783 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5784 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005785 err_code |= ERR_ALERT | ERR_FATAL;
5786 goto out;
5787 }
5788
5789 if (port1 != port2) {
5790 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5791 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005792 err_code |= ERR_ALERT | ERR_FATAL;
5793 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005794 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005795
5796 if (!port1) {
5797 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5798 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005799 err_code |= ERR_ALERT | ERR_FATAL;
5800 goto out;
5801 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005802
William Lallemanddf1425a2015-04-28 20:17:49 +02005803 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5804 goto out;
5805
Willy Tarreaud5191e72010-02-09 20:50:45 +01005806 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005807 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005808 }
5809 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005810 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005811 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005812
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005813 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5814 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005815 err_code |= ERR_ALERT | ERR_FATAL;
5816 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005817 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005818 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005819 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005820 /**
5821 * The syntax for hash-type config element is
5822 * hash-type {map-based|consistent} [[<algo>] avalanche]
5823 *
5824 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5825 */
5826 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005827
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005828 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5829 err_code |= ERR_WARN;
5830
5831 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005832 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5833 }
5834 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005835 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5836 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005837 else if (strcmp(args[1], "avalanche") == 0) {
5838 Alert("parsing [%s:%d] : experimental feature '%s %s' is not supported anymore, please use '%s map-based sdbm avalanche' instead.\n", file, linenum, args[0], args[1], args[0]);
5839 err_code |= ERR_ALERT | ERR_FATAL;
5840 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005841 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005842 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005843 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005844 err_code |= ERR_ALERT | ERR_FATAL;
5845 goto out;
5846 }
Bhaskar98634f02013-10-29 23:30:51 -04005847
5848 /* set the hash function to use */
5849 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005850 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005851 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005852
5853 /* if consistent with no argument, then avalanche modifier is also applied */
5854 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5855 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005856 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005857 /* set the hash function */
5858 if (!strcmp(args[2], "sdbm")) {
5859 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5860 }
5861 else if (!strcmp(args[2], "djb2")) {
5862 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005863 }
5864 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005865 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005866 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005867 else if (!strcmp(args[2], "crc32")) {
5868 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5869 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005870 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005871 Alert("parsing [%s:%d] : '%s' only supports 'sdbm', 'djb2', 'crc32', or 'wt6' hash functions.\n", file, linenum, args[0]);
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005872 err_code |= ERR_ALERT | ERR_FATAL;
5873 goto out;
5874 }
5875
5876 /* set the hash modifier */
5877 if (!strcmp(args[3], "avalanche")) {
5878 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5879 }
5880 else if (*args[3]) {
5881 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5882 err_code |= ERR_ALERT | ERR_FATAL;
5883 goto out;
5884 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005885 }
William Lallemanda73203e2012-03-12 12:48:57 +01005886 }
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04005887 else if (strcmp(args[0], "hash-balance-factor") == 0) {
5888 if (*(args[1]) == 0) {
5889 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
5890 err_code |= ERR_ALERT | ERR_FATAL;
5891 goto out;
5892 }
5893 curproxy->lbprm.chash.balance_factor = atol(args[1]);
5894 if (curproxy->lbprm.chash.balance_factor != 0 && curproxy->lbprm.chash.balance_factor <= 100) {
5895 Alert("parsing [%s:%d] : '%s' must be 0 or greater than 100.\n", file, linenum, args[0]);
5896 err_code |= ERR_ALERT | ERR_FATAL;
5897 goto out;
5898 }
5899 }
William Lallemanda73203e2012-03-12 12:48:57 +01005900 else if (strcmp(args[0], "unique-id-format") == 0) {
5901 if (!*(args[1])) {
5902 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5903 err_code |= ERR_ALERT | ERR_FATAL;
5904 goto out;
5905 }
William Lallemand3203ff42012-11-11 17:30:56 +01005906 if (*(args[2])) {
5907 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5908 err_code |= ERR_ALERT | ERR_FATAL;
5909 goto out;
5910 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005911 free(curproxy->conf.uniqueid_format_string);
5912 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005913
Willy Tarreau62a61232013-04-12 18:13:46 +02005914 free(curproxy->conf.uif_file);
5915 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5916 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005917 }
William Lallemanda73203e2012-03-12 12:48:57 +01005918
5919 else if (strcmp(args[0], "unique-id-header") == 0) {
5920 if (!*(args[1])) {
5921 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5922 err_code |= ERR_ALERT | ERR_FATAL;
5923 goto out;
5924 }
5925 free(curproxy->header_unique_id);
5926 curproxy->header_unique_id = strdup(args[1]);
5927 }
5928
William Lallemand723b73a2012-02-08 16:37:49 +01005929 else if (strcmp(args[0], "log-format") == 0) {
5930 if (!*(args[1])) {
5931 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5932 err_code |= ERR_ALERT | ERR_FATAL;
5933 goto out;
5934 }
William Lallemand3203ff42012-11-11 17:30:56 +01005935 if (*(args[2])) {
5936 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5937 err_code |= ERR_ALERT | ERR_FATAL;
5938 goto out;
5939 }
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02005940 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
5941 char *oldlogformat = "log-format";
Willy Tarreau196729e2012-05-31 19:30:26 +02005942
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02005943 if (curproxy->conf.logformat_string == default_http_log_format)
5944 oldlogformat = "option httplog";
5945 else if (curproxy->conf.logformat_string == default_tcp_log_format)
5946 oldlogformat = "option tcplog";
5947 else if (curproxy->conf.logformat_string == clf_http_log_format)
5948 oldlogformat = "option httplog clf";
5949 Warning("parsing [%s:%d]: 'log-format' overrides previous '%s' in 'defaults' section.\n",
5950 file, linenum, oldlogformat);
5951 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005952 if (curproxy->conf.logformat_string != default_http_log_format &&
5953 curproxy->conf.logformat_string != default_tcp_log_format &&
5954 curproxy->conf.logformat_string != clf_http_log_format)
5955 free(curproxy->conf.logformat_string);
5956 curproxy->conf.logformat_string = strdup(args[1]);
5957
5958 free(curproxy->conf.lfs_file);
5959 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5960 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005961
5962 /* get a chance to improve log-format error reporting by
5963 * reporting the correct line-number when possible.
5964 */
5965 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5966 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5967 file, linenum, curproxy->id);
5968 err_code |= ERR_WARN;
5969 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005970 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02005971 else if (!strcmp(args[0], "log-format-sd")) {
5972 if (!*(args[1])) {
5973 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5974 err_code |= ERR_ALERT | ERR_FATAL;
5975 goto out;
5976 }
5977 if (*(args[2])) {
5978 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5979 err_code |= ERR_ALERT | ERR_FATAL;
5980 goto out;
5981 }
5982
5983 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
5984 free(curproxy->conf.logformat_sd_string);
5985 curproxy->conf.logformat_sd_string = strdup(args[1]);
5986
5987 free(curproxy->conf.lfsd_file);
5988 curproxy->conf.lfsd_file = strdup(curproxy->conf.args.file);
5989 curproxy->conf.lfsd_line = curproxy->conf.args.line;
5990
5991 /* get a chance to improve log-format-sd error reporting by
5992 * reporting the correct line-number when possible.
5993 */
5994 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5995 Warning("parsing [%s:%d] : backend '%s' : 'log-format-sd' directive is ignored in backends.\n",
5996 file, linenum, curproxy->id);
5997 err_code |= ERR_WARN;
5998 }
5999 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01006000 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
6001 if (*(args[1]) == 0) {
6002 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
6003 err_code |= ERR_ALERT | ERR_FATAL;
6004 goto out;
6005 }
Dragan Dosen43885c72015-10-01 13:18:13 +02006006 chunk_destroy(&curproxy->log_tag);
6007 chunk_initstr(&curproxy->log_tag, strdup(args[1]));
Willy Tarreau094af4e2015-01-07 15:03:42 +01006008 }
William Lallemand0f99e342011-10-12 17:50:54 +02006009 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
6010 /* delete previous herited or defined syslog servers */
6011 struct logsrv *back;
6012
6013 if (*(args[1]) != 0) {
6014 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
6015 err_code |= ERR_ALERT | ERR_FATAL;
6016 goto out;
6017 }
6018
William Lallemand723b73a2012-02-08 16:37:49 +01006019 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
6020 LIST_DEL(&tmplogsrv->list);
6021 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02006022 }
6023 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006024 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02006025 struct logsrv *logsrv;
6026
Willy Tarreaubaaee002006-06-26 02:48:02 +02006027 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006028 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01006029 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02006030 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01006031 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02006032 LIST_INIT(&node->list);
6033 LIST_ADDQ(&curproxy->logsrvs, &node->list);
6034 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006035 }
6036 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006037 struct sockaddr_storage *sk;
6038 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02006039 int arg = 0;
6040 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02006041
Vincent Bernat02779b62016-04-03 13:48:43 +02006042 logsrv = calloc(1, sizeof(*logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006043
Willy Tarreau18324f52014-06-27 18:10:07 +02006044 /* just after the address, a length may be specified */
6045 if (strcmp(args[arg+2], "len") == 0) {
6046 len = atoi(args[arg+3]);
6047 if (len < 80 || len > 65535) {
6048 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
6049 file, linenum, args[arg+3]);
6050 err_code |= ERR_ALERT | ERR_FATAL;
6051 goto out;
6052 }
6053 logsrv->maxlen = len;
6054
6055 /* skip these two args */
6056 arg += 2;
6057 }
6058 else
6059 logsrv->maxlen = MAX_SYSLOG_LEN;
6060
6061 if (logsrv->maxlen > global.max_syslog_len) {
6062 global.max_syslog_len = logsrv->maxlen;
Hubert Verstraete831962e2016-06-28 22:44:26 +02006063 logheader = my_realloc2(logheader, global.max_syslog_len + 1);
6064 logheader_rfc5424 = my_realloc2(logheader_rfc5424, global.max_syslog_len + 1);
6065 logline = my_realloc2(logline, global.max_syslog_len + 1);
6066 logline_rfc5424 = my_realloc2(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02006067 }
6068
Dragan Dosen1322d092015-09-22 16:05:32 +02006069 /* after the length, a format may be specified */
6070 if (strcmp(args[arg+2], "format") == 0) {
6071 logsrv->format = get_log_format(args[arg+3]);
6072 if (logsrv->format < 0) {
6073 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
6074 err_code |= ERR_ALERT | ERR_FATAL;
6075 goto out;
6076 }
6077
6078 /* skip these two args */
6079 arg += 2;
6080 }
6081
William Lallemanddf1425a2015-04-28 20:17:49 +02006082 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
6083 goto out;
6084
Willy Tarreau18324f52014-06-27 18:10:07 +02006085 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006086 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006087 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006088 err_code |= ERR_ALERT | ERR_FATAL;
6089 goto out;
6090
Willy Tarreaubaaee002006-06-26 02:48:02 +02006091 }
6092
William Lallemand0f99e342011-10-12 17:50:54 +02006093 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02006094 if (*(args[arg+3])) {
6095 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006096 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006097 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006098 err_code |= ERR_ALERT | ERR_FATAL;
6099 goto out;
6100
Willy Tarreaubaaee002006-06-26 02:48:02 +02006101 }
6102 }
6103
William Lallemand0f99e342011-10-12 17:50:54 +02006104 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02006105 if (*(args[arg+4])) {
6106 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01006107 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006108 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02006109 err_code |= ERR_ALERT | ERR_FATAL;
6110 goto out;
6111
Willy Tarreauf7edefa2009-05-10 17:20:05 +02006112 }
6113 }
6114
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006115 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006116 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01006117 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006118 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006119 goto out;
6120 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006121
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006122 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006123
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006124 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006125 if (port1 != port2) {
6126 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6127 file, linenum, args[0], args[1]);
6128 err_code |= ERR_ALERT | ERR_FATAL;
6129 goto out;
6130 }
6131
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006132 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02006133 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006134 }
William Lallemand0f99e342011-10-12 17:50:54 +02006135
6136 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006137 }
6138 else {
6139 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
6140 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02006141 err_code |= ERR_ALERT | ERR_FATAL;
6142 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006143 }
6144 }
6145 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006146 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006147 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01006148 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006149 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006150
Willy Tarreau977b8e42006-12-29 14:19:17 +01006151 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006152 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006153
Willy Tarreaubaaee002006-06-26 02:48:02 +02006154 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006155 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
6156 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02006157 err_code |= ERR_ALERT | ERR_FATAL;
6158 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006159 }
Willy Tarreau368480c2009-03-01 08:27:21 +01006160
6161 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01006162 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6163 free(curproxy->conn_src.iface_name);
6164 curproxy->conn_src.iface_name = NULL;
6165 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01006166
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006167 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006168 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006169 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006170 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006171 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006172 goto out;
6173 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006174
6175 proto = protocol_by_family(sk->ss_family);
6176 if (!proto || !proto->connect) {
6177 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006178 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006179 err_code |= ERR_ALERT | ERR_FATAL;
6180 goto out;
6181 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006182
6183 if (port1 != port2) {
6184 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6185 file, linenum, args[0], args[1]);
6186 err_code |= ERR_ALERT | ERR_FATAL;
6187 goto out;
6188 }
6189
Willy Tarreauef9a3602012-12-08 22:29:20 +01006190 curproxy->conn_src.source_addr = *sk;
6191 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006192
6193 cur_arg = 2;
6194 while (*(args[cur_arg])) {
6195 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau29fbe512015-08-20 19:35:14 +02006196#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006197 if (!*args[cur_arg + 1]) {
6198 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
6199 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006200 err_code |= ERR_ALERT | ERR_FATAL;
6201 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006202 }
6203
6204 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006205 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6206 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006207 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006208 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6209 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02006210 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
6211 char *name, *end;
6212
6213 name = args[cur_arg+1] + 7;
6214 while (isspace(*name))
6215 name++;
6216
6217 end = name;
6218 while (*end && !isspace(*end) && *end != ',' && *end != ')')
6219 end++;
6220
Willy Tarreauef9a3602012-12-08 22:29:20 +01006221 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6222 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
6223 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
6224 curproxy->conn_src.bind_hdr_len = end - name;
6225 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
6226 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
6227 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02006228
6229 /* now look for an occurrence number */
6230 while (isspace(*end))
6231 end++;
6232 if (*end == ',') {
6233 end++;
6234 name = end;
6235 if (*end == '-')
6236 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01006237 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02006238 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01006239 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006240 }
6241
Willy Tarreauef9a3602012-12-08 22:29:20 +01006242 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02006243 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
6244 " occurrences values smaller than %d.\n",
6245 file, linenum, MAX_HDR_HISTORY);
6246 err_code |= ERR_ALERT | ERR_FATAL;
6247 goto out;
6248 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006249 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01006250 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006251
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006252 sk = str2sa_range(args[cur_arg + 1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006253 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006254 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006255 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006256 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006257 goto out;
6258 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006259
6260 proto = protocol_by_family(sk->ss_family);
6261 if (!proto || !proto->connect) {
6262 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
6263 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006264 err_code |= ERR_ALERT | ERR_FATAL;
6265 goto out;
6266 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006267
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006268 if (port1 != port2) {
6269 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6270 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006271 err_code |= ERR_ALERT | ERR_FATAL;
6272 goto out;
6273 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006274 curproxy->conn_src.tproxy_addr = *sk;
6275 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006276 }
6277 global.last_checks |= LSTCHK_NETADM;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006278#else /* no TPROXY support */
6279 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01006280 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006281 err_code |= ERR_ALERT | ERR_FATAL;
6282 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006283#endif
6284 cur_arg += 2;
6285 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01006286 }
6287
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006288 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
6289#ifdef SO_BINDTODEVICE
6290 if (!*args[cur_arg + 1]) {
6291 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
6292 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006293 err_code |= ERR_ALERT | ERR_FATAL;
6294 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006295 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006296 free(curproxy->conn_src.iface_name);
6297 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
6298 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006299 global.last_checks |= LSTCHK_NETADM;
6300#else
6301 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
6302 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02006303 err_code |= ERR_ALERT | ERR_FATAL;
6304 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01006305#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006306 cur_arg += 2;
6307 continue;
6308 }
6309 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02006310 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006311 err_code |= ERR_ALERT | ERR_FATAL;
6312 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006313 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006314 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006315 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
6316 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
6317 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02006318 err_code |= ERR_ALERT | ERR_FATAL;
6319 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006320 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006321 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006322 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006323 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6324 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006325 err_code |= ERR_ALERT | ERR_FATAL;
6326 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006327 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006328
6329 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006330 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006331 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006332 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006333 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006334 }
6335 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006336 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006337 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006338 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006339 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006340 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006341 }
6342 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006343 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006344 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006345 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006346 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006347 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006348 }
6349 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006350 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006351 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006352 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006353 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006354 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006355 }
6356 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006357 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006358 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006359 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006360 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006361 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006362 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006363 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006364 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006365 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006366 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006367 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006368 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006369 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006370 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006371 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006372 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6373 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006374 err_code |= ERR_ALERT | ERR_FATAL;
6375 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006376 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006377
6378 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006379 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006380 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006381 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006382 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006383 }
6384 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006385 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006386 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006387 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006388 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006389 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006390 }
6391 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006392 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006393 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006394 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006395 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006396 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006397 }
6398 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006399 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006400 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006401 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006402 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006403 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006404 }
6405 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006406 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006407 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006408 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006409 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006410 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006411 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006412 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006413 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006414 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006415 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006416 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006417 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006418 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006419 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006420 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006421
Willy Tarreaubaaee002006-06-26 02:48:02 +02006422 if (curproxy == &defproxy) {
6423 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006424 err_code |= ERR_ALERT | ERR_FATAL;
6425 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006426 }
Christopher Faulet898566e2016-10-26 11:06:28 +02006427 else if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006428 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006429
Willy Tarreaubaaee002006-06-26 02:48:02 +02006430 if (*(args[1]) == 0) {
6431 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006432 err_code |= ERR_ALERT | ERR_FATAL;
6433 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006434 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006435
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006436 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006437 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6438 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6439 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006440 err_code |= ERR_ALERT | ERR_FATAL;
6441 goto out;
6442 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006443 err_code |= warnif_cond_conflicts(cond,
6444 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6445 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006446 }
6447 else if (*args[2]) {
6448 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6449 file, linenum, args[0], args[2]);
6450 err_code |= ERR_ALERT | ERR_FATAL;
6451 goto out;
6452 }
6453
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006454 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006455 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006456 wl->s = strdup(args[1]);
6457 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02006458 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006459 }
6460 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006461 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006462 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6463 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006464 err_code |= ERR_ALERT | ERR_FATAL;
6465 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006466 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006467
Willy Tarreauade5ec42010-01-28 19:33:49 +01006468 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006469 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006470 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006471 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006472 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006473 }
6474 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006475 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006476 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006477 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006478 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006479 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006480 }
6481 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006482 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006483 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006484 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006485 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006486 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006487 }
6488 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006489 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006490 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6491 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006492 err_code |= ERR_ALERT | ERR_FATAL;
6493 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006494 }
6495
Willy Tarreauade5ec42010-01-28 19:33:49 +01006496 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006497 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006498 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006499 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006500 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006501 }
6502 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006503 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006504 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006505 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006506 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006507 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006508 }
6509 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006510 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006511 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006512 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006513 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006514 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006515 }
6516 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006517 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006518
Willy Tarreaubaaee002006-06-26 02:48:02 +02006519 if (curproxy == &defproxy) {
6520 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006521 err_code |= ERR_ALERT | ERR_FATAL;
6522 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006523 }
Christopher Faulet898566e2016-10-26 11:06:28 +02006524 else if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006525 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006526
Willy Tarreaubaaee002006-06-26 02:48:02 +02006527 if (*(args[1]) == 0) {
6528 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006529 err_code |= ERR_ALERT | ERR_FATAL;
6530 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006531 }
6532
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006533 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006534 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6535 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6536 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006537 err_code |= ERR_ALERT | ERR_FATAL;
6538 goto out;
6539 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006540 err_code |= warnif_cond_conflicts(cond,
6541 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
6542 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006543 }
6544 else if (*args[2]) {
6545 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6546 file, linenum, args[0], args[2]);
6547 err_code |= ERR_ALERT | ERR_FATAL;
6548 goto out;
6549 }
6550
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006551 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006552 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006553 wl->s = strdup(args[1]);
6554 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006555 }
6556 else if (!strcmp(args[0], "errorloc") ||
6557 !strcmp(args[0], "errorloc302") ||
6558 !strcmp(args[0], "errorloc303")) { /* error location */
6559 int errnum, errlen;
6560 char *err;
6561
Willy Tarreau977b8e42006-12-29 14:19:17 +01006562 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006563 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006564
Willy Tarreaubaaee002006-06-26 02:48:02 +02006565 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006566 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006567 err_code |= ERR_ALERT | ERR_FATAL;
6568 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006569 }
6570
6571 errnum = atol(args[1]);
6572 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006573 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
6574 err = malloc(errlen);
6575 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006576 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006577 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
6578 err = malloc(errlen);
6579 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006580 }
6581
Willy Tarreau0f772532006-12-23 20:51:41 +01006582 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6583 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006584 chunk_destroy(&curproxy->errmsg[rc]);
6585 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01006586 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006587 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006588 }
Willy Tarreau0f772532006-12-23 20:51:41 +01006589
6590 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006591 Warning("parsing [%s:%d] : status code %d not handled by '%s', error relocation will be ignored.\n",
6592 file, linenum, errnum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006593 free(err);
6594 }
6595 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02006596 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
6597 int errnum, errlen, fd;
6598 char *err;
6599 struct stat stat;
6600
6601 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006602 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006603
6604 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006605 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006606 err_code |= ERR_ALERT | ERR_FATAL;
6607 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006608 }
6609
6610 fd = open(args[2], O_RDONLY);
6611 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
6612 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
6613 file, linenum, args[2], args[1]);
6614 if (fd >= 0)
6615 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02006616 err_code |= ERR_ALERT | ERR_FATAL;
6617 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006618 }
6619
Willy Tarreau27a674e2009-08-17 07:23:33 +02006620 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02006621 errlen = stat.st_size;
6622 } else {
6623 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02006624 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02006625 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02006626 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006627 }
6628
6629 err = malloc(errlen); /* malloc() must succeed during parsing */
6630 errnum = read(fd, err, errlen);
6631 if (errnum != errlen) {
6632 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
6633 file, linenum, args[2], args[1]);
6634 close(fd);
6635 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02006636 err_code |= ERR_ALERT | ERR_FATAL;
6637 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006638 }
6639 close(fd);
6640
6641 errnum = atol(args[1]);
6642 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6643 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006644 chunk_destroy(&curproxy->errmsg[rc]);
6645 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02006646 break;
6647 }
6648 }
6649
6650 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006651 Warning("parsing [%s:%d] : status code %d not handled by '%s', error customization will be ignored.\n",
6652 file, linenum, errnum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006653 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006654 free(err);
6655 }
6656 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006657 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006658 struct cfg_kw_list *kwl;
6659 int index;
6660
6661 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6662 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6663 if (kwl->kw[index].section != CFG_LISTEN)
6664 continue;
6665 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6666 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006667 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006668 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006669 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006670 err_code |= ERR_ALERT | ERR_FATAL;
6671 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006672 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006673 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006674 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006675 err_code |= ERR_WARN;
6676 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006677 }
Willy Tarreau93893792009-07-23 13:19:11 +02006678 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006679 }
6680 }
6681 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006682
Willy Tarreau6daf3432008-01-22 16:44:08 +01006683 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006684 err_code |= ERR_ALERT | ERR_FATAL;
6685 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006686 }
Willy Tarreau93893792009-07-23 13:19:11 +02006687 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006688 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006689 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006690}
6691
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006692int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006693cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
6694{
6695#ifdef CONFIG_HAP_NS
6696 const char *err;
6697 const char *item = args[0];
6698
6699 if (!strcmp(item, "namespace_list")) {
6700 return 0;
6701 }
6702 else if (!strcmp(item, "namespace")) {
6703 size_t idx = 1;
6704 const char *current;
6705 while (*(current = args[idx++])) {
6706 err = invalid_char(current);
6707 if (err) {
6708 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6709 file, linenum, *err, item, current);
6710 return ERR_ALERT | ERR_FATAL;
6711 }
6712
6713 if (netns_store_lookup(current, strlen(current))) {
6714 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
6715 file, linenum, current);
6716 return ERR_ALERT | ERR_FATAL;
6717 }
6718 if (!netns_store_insert(current)) {
6719 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
6720 file, linenum, current);
6721 return ERR_ALERT | ERR_FATAL;
6722 }
6723 }
6724 }
6725
6726 return 0;
6727#else
6728 Alert("parsing [%s:%d]: namespace support is not compiled in.",
6729 file, linenum);
6730 return ERR_ALERT | ERR_FATAL;
6731#endif
6732}
6733
6734int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006735cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6736{
6737
6738 int err_code = 0;
6739 const char *err;
6740
6741 if (!strcmp(args[0], "userlist")) { /* new userlist */
6742 struct userlist *newul;
6743
6744 if (!*args[1]) {
6745 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6746 file, linenum, args[0]);
6747 err_code |= ERR_ALERT | ERR_FATAL;
6748 goto out;
6749 }
William Lallemand6e62fb62015-04-28 16:55:23 +02006750 if (alertif_too_many_args(1, file, linenum, args, &err_code))
6751 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006752
6753 err = invalid_char(args[1]);
6754 if (err) {
6755 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6756 file, linenum, *err, args[0], args[1]);
6757 err_code |= ERR_ALERT | ERR_FATAL;
6758 goto out;
6759 }
6760
6761 for (newul = userlist; newul; newul = newul->next)
6762 if (!strcmp(newul->name, args[1])) {
6763 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6764 file, linenum, args[1]);
6765 err_code |= ERR_WARN;
6766 goto out;
6767 }
6768
Vincent Bernat02779b62016-04-03 13:48:43 +02006769 newul = calloc(1, sizeof(*newul));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006770 if (!newul) {
6771 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6772 err_code |= ERR_ALERT | ERR_ABORT;
6773 goto out;
6774 }
6775
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006776 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006777 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006778 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6779 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier97880bb2016-04-08 10:35:26 +01006780 free(newul);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006781 goto out;
6782 }
6783
6784 newul->next = userlist;
6785 userlist = newul;
6786
6787 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006788 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006789 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006790 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006791
6792 if (!*args[1]) {
6793 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6794 file, linenum, args[0]);
6795 err_code |= ERR_ALERT | ERR_FATAL;
6796 goto out;
6797 }
6798
6799 err = invalid_char(args[1]);
6800 if (err) {
6801 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6802 file, linenum, *err, args[0], args[1]);
6803 err_code |= ERR_ALERT | ERR_FATAL;
6804 goto out;
6805 }
6806
William Lallemand4ac9f542015-05-28 18:03:51 +02006807 if (!userlist)
6808 goto out;
6809
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006810 for (ag = userlist->groups; ag; ag = ag->next)
6811 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006812 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6813 file, linenum, args[1], userlist->name);
6814 err_code |= ERR_ALERT;
6815 goto out;
6816 }
6817
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006818 ag = calloc(1, sizeof(*ag));
6819 if (!ag) {
6820 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6821 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006822 goto out;
6823 }
6824
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006825 ag->name = strdup(args[1]);
David Carlier70d60452016-08-22 23:27:42 +01006826 if (!ag->name) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006827 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6828 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier70d60452016-08-22 23:27:42 +01006829 free(ag);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006830 goto out;
6831 }
6832
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006833 cur_arg = 2;
6834
6835 while (*args[cur_arg]) {
6836 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006837 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006838 cur_arg += 2;
6839 continue;
6840 } else {
6841 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6842 file, linenum, args[0]);
6843 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01006844 free(ag->groupusers);
6845 free(ag->name);
6846 free(ag);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006847 goto out;
6848 }
6849 }
6850
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006851 ag->next = userlist->groups;
6852 userlist->groups = ag;
6853
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006854 } else if (!strcmp(args[0], "user")) { /* new user */
6855 struct auth_users *newuser;
6856 int cur_arg;
6857
6858 if (!*args[1]) {
6859 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6860 file, linenum, args[0]);
6861 err_code |= ERR_ALERT | ERR_FATAL;
6862 goto out;
6863 }
William Lallemand4ac9f542015-05-28 18:03:51 +02006864 if (!userlist)
6865 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006866
6867 for (newuser = userlist->users; newuser; newuser = newuser->next)
6868 if (!strcmp(newuser->user, args[1])) {
6869 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6870 file, linenum, args[1], userlist->name);
6871 err_code |= ERR_ALERT;
6872 goto out;
6873 }
6874
Vincent Bernat02779b62016-04-03 13:48:43 +02006875 newuser = calloc(1, sizeof(*newuser));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006876 if (!newuser) {
6877 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6878 err_code |= ERR_ALERT | ERR_ABORT;
6879 goto out;
6880 }
6881
6882 newuser->user = strdup(args[1]);
6883
6884 newuser->next = userlist->users;
6885 userlist->users = newuser;
6886
6887 cur_arg = 2;
6888
6889 while (*args[cur_arg]) {
6890 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006891#ifdef CONFIG_HAP_CRYPT
6892 if (!crypt("", args[cur_arg + 1])) {
6893 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6894 file, linenum, newuser->user);
6895 err_code |= ERR_ALERT | ERR_FATAL;
6896 goto out;
6897 }
6898#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006899 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6900 file, linenum);
6901 err_code |= ERR_ALERT;
6902#endif
6903 newuser->pass = strdup(args[cur_arg + 1]);
6904 cur_arg += 2;
6905 continue;
6906 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6907 newuser->pass = strdup(args[cur_arg + 1]);
6908 newuser->flags |= AU_O_INSECURE;
6909 cur_arg += 2;
6910 continue;
6911 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006912 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006913 cur_arg += 2;
6914 continue;
6915 } else {
6916 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6917 file, linenum, args[0]);
6918 err_code |= ERR_ALERT | ERR_FATAL;
6919 goto out;
6920 }
6921 }
6922 } else {
6923 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6924 err_code |= ERR_ALERT | ERR_FATAL;
6925 }
6926
6927out:
6928 return err_code;
6929}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006930
Christopher Faulet79bdef32016-11-04 22:36:15 +01006931int
6932cfg_parse_scope(const char *file, int linenum, char *line)
6933{
6934 char *beg, *end, *scope = NULL;
6935 int err_code = 0;
6936 const char *err;
6937
6938 beg = line + 1;
6939 end = strchr(beg, ']');
6940
6941 /* Detect end of scope declaration */
6942 if (!end || end == beg) {
6943 Alert("parsing [%s:%d] : empty scope name is forbidden.\n",
6944 file, linenum);
6945 err_code |= ERR_ALERT | ERR_FATAL;
6946 goto out;
6947 }
6948
6949 /* Get scope name and check its validity */
6950 scope = my_strndup(beg, end-beg);
6951 err = invalid_char(scope);
6952 if (err) {
6953 Alert("parsing [%s:%d] : character '%c' is not permitted in a scope name.\n",
6954 file, linenum, *err);
6955 err_code |= ERR_ALERT | ERR_ABORT;
6956 goto out;
6957 }
6958
6959 /* Be sure to have a scope declaration alone on its line */
6960 line = end+1;
6961 while (isspace((unsigned char)*line))
6962 line++;
6963 if (*line && *line != '#' && *line != '\n' && *line != '\r') {
6964 Alert("parsing [%s:%d] : character '%c' is not permitted after scope declaration.\n",
6965 file, linenum, *line);
6966 err_code |= ERR_ALERT | ERR_ABORT;
6967 goto out;
6968 }
6969
6970 /* We have a valid scope declaration, save it */
6971 free(cfg_scope);
6972 cfg_scope = scope;
6973 scope = NULL;
6974
6975 out:
6976 free(scope);
6977 return err_code;
6978}
6979
Willy Tarreaubaaee002006-06-26 02:48:02 +02006980/*
6981 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006982 * Returns the error code, 0 if OK, or any combination of :
6983 * - ERR_ABORT: must abort ASAP
6984 * - ERR_FATAL: we can continue parsing but not start the service
6985 * - ERR_WARN: a warning has been emitted
6986 * - ERR_ALERT: an alert has been emitted
6987 * Only the two first ones can stop processing, the two others are just
6988 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006989 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006990int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006991{
William Lallemand64e84512015-05-12 14:25:37 +02006992 char *thisline;
6993 int linesize = LINESIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006994 FILE *f;
6995 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02006996 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006997 struct cfg_section *cs = NULL;
6998 struct cfg_section *ics;
William Lallemand64e84512015-05-12 14:25:37 +02006999 int readbytes = 0;
7000
7001 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
William Lallemandb2f07452015-05-12 14:27:13 +02007002 Alert("parsing [%s] : out of memory.\n", file);
William Lallemand64e84512015-05-12 14:25:37 +02007003 return -1;
7004 }
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007005
David Carlier97880bb2016-04-08 10:35:26 +01007006 if ((f=fopen(file,"r")) == NULL) {
7007 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007008 return -1;
David Carlier97880bb2016-04-08 10:35:26 +01007009 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007010
William Lallemandb2f07452015-05-12 14:27:13 +02007011next_line:
William Lallemand64e84512015-05-12 14:25:37 +02007012 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02007013 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007014 char *end;
7015 char *args[MAX_LINE_ARGS + 1];
7016 char *line = thisline;
William Lallemandf9873ba2015-05-05 17:37:14 +02007017 int dquote = 0; /* double quote */
7018 int squote = 0; /* simple quote */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007019
Willy Tarreaubaaee002006-06-26 02:48:02 +02007020 linenum++;
7021
7022 end = line + strlen(line);
7023
William Lallemand64e84512015-05-12 14:25:37 +02007024 if (end-line == linesize-1 && *(end-1) != '\n') {
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007025 /* Check if we reached the limit and the last char is not \n.
7026 * Watch out for the last line without the terminating '\n'!
7027 */
William Lallemand64e84512015-05-12 14:25:37 +02007028 char *newline;
7029 int newlinesize = linesize * 2;
7030
7031 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
7032 if (newline == NULL) {
7033 Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
7034 file, linenum);
7035 err_code |= ERR_ALERT | ERR_FATAL;
7036 continue;
7037 }
7038
7039 readbytes = linesize - 1;
7040 linesize = newlinesize;
7041 thisline = newline;
7042 continue;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007043 }
7044
William Lallemand64e84512015-05-12 14:25:37 +02007045 readbytes = 0;
7046
Willy Tarreaubaaee002006-06-26 02:48:02 +02007047 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007048 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007049 line++;
William Lallemandf9873ba2015-05-05 17:37:14 +02007050
Christopher Faulet79bdef32016-11-04 22:36:15 +01007051
7052 if (*line == '[') {/* This is the begining if a scope */
7053 err_code |= cfg_parse_scope(file, linenum, line);
7054 goto next_line;
7055 }
7056
Willy Tarreaubaaee002006-06-26 02:48:02 +02007057 arg = 0;
7058 args[arg] = line;
7059
7060 while (*line && arg < MAX_LINE_ARGS) {
William Lallemandf9873ba2015-05-05 17:37:14 +02007061 if (*line == '"' && !squote) { /* double quote outside single quotes */
7062 if (dquote)
7063 dquote = 0;
7064 else
7065 dquote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007066 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007067 end--;
7068 }
7069 else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
7070 if (squote)
7071 squote = 0;
7072 else
7073 squote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007074 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007075 end--;
7076 }
7077 else if (*line == '\\' && !squote) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007078 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
7079 * C equivalent value. Other combinations left unchanged (eg: \1).
7080 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007081 int skip = 0;
7082 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
7083 *line = line[1];
7084 skip = 1;
7085 }
7086 else if (line[1] == 'r') {
7087 *line = '\r';
7088 skip = 1;
William Lallemandf9873ba2015-05-05 17:37:14 +02007089 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007090 else if (line[1] == 'n') {
7091 *line = '\n';
7092 skip = 1;
7093 }
7094 else if (line[1] == 't') {
7095 *line = '\t';
7096 skip = 1;
7097 }
7098 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01007099 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007100 unsigned char hex1, hex2;
7101 hex1 = toupper(line[2]) - '0';
7102 hex2 = toupper(line[3]) - '0';
7103 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
7104 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
7105 *line = (hex1<<4) + hex2;
7106 skip = 3;
7107 }
7108 else {
7109 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007110 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007111 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007112 } else if (line[1] == '"') {
7113 *line = '"';
7114 skip = 1;
7115 } else if (line[1] == '\'') {
7116 *line = '\'';
7117 skip = 1;
William Lallemandb2f07452015-05-12 14:27:13 +02007118 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
7119 *line = '$';
7120 skip = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007121 }
7122 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01007123 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02007124 end -= skip;
7125 }
7126 line++;
7127 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007128 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007129 /* end of string, end of loop */
7130 *line = 0;
7131 break;
7132 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007133 else if (!squote && !dquote && isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007134 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007135 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007136 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007137 line++;
7138 args[++arg] = line;
7139 }
William Lallemandb2f07452015-05-12 14:27:13 +02007140 else if (dquote && *line == '$') {
7141 /* environment variables are evaluated inside double quotes */
7142 char *var_beg;
7143 char *var_end;
7144 char save_char;
7145 char *value;
7146 int val_len;
7147 int newlinesize;
7148 int braces = 0;
7149
7150 var_beg = line + 1;
7151 var_end = var_beg;
7152
7153 if (*var_beg == '{') {
7154 var_beg++;
7155 var_end++;
7156 braces = 1;
7157 }
7158
7159 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
7160 Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
7161 err_code |= ERR_ALERT | ERR_FATAL;
7162 goto next_line; /* skip current line */
7163 }
7164
7165 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
7166 var_end++;
7167
7168 save_char = *var_end;
7169 *var_end = '\0';
7170 value = getenv(var_beg);
7171 *var_end = save_char;
7172 val_len = value ? strlen(value) : 0;
7173
7174 if (braces) {
7175 if (*var_end == '}') {
7176 var_end++;
7177 braces = 0;
7178 } else {
7179 Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
7180 err_code |= ERR_ALERT | ERR_FATAL;
7181 goto next_line; /* skip current line */
7182 }
7183 }
7184
7185 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
7186
7187 /* if not enough space in thisline */
7188 if (newlinesize > linesize) {
7189 char *newline;
7190
7191 newline = realloc(thisline, newlinesize * sizeof(*thisline));
7192 if (newline == NULL) {
7193 Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
7194 err_code |= ERR_ALERT | ERR_FATAL;
7195 goto next_line; /* slip current line */
7196 }
7197 /* recompute pointers if realloc returns a new pointer */
7198 if (newline != thisline) {
7199 int i;
7200 int diff;
7201
7202 for (i = 0; i <= arg; i++) {
7203 diff = args[i] - thisline;
7204 args[i] = newline + diff;
7205 }
7206
7207 diff = var_end - thisline;
7208 var_end = newline + diff;
7209 diff = end - thisline;
7210 end = newline + diff;
7211 diff = line - thisline;
7212 line = newline + diff;
7213 thisline = newline;
7214 }
7215 linesize = newlinesize;
7216 }
7217
7218 /* insert value inside the line */
7219 memmove(line + val_len, var_end, end - var_end + 1);
7220 memcpy(line, value, val_len);
7221 end += val_len - (var_end - line);
7222 line += val_len;
7223 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007224 else {
7225 line++;
7226 }
7227 }
William Lallemandb2f07452015-05-12 14:27:13 +02007228
William Lallemandf9873ba2015-05-05 17:37:14 +02007229 if (dquote) {
7230 Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
7231 err_code |= ERR_ALERT | ERR_FATAL;
7232 }
7233
7234 if (squote) {
7235 Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
7236 err_code |= ERR_ALERT | ERR_FATAL;
7237 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007238
7239 /* empty line */
7240 if (!**args)
7241 continue;
7242
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007243 if (*line) {
7244 /* we had to stop due to too many args.
7245 * Let's terminate the string, print the offending part then cut the
7246 * last arg.
7247 */
7248 while (*line && *line != '#' && *line != '\n' && *line != '\r')
7249 line++;
7250 *line = '\0';
7251
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01007252 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01007253 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007254 err_code |= ERR_ALERT | ERR_FATAL;
7255 args[arg] = line;
7256 }
7257
Willy Tarreau540abe42007-05-02 20:50:16 +02007258 /* zero out remaining args and ensure that at least one entry
7259 * is zeroed out.
7260 */
7261 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007262 args[arg] = line;
7263 }
7264
Willy Tarreau3842f002009-06-14 11:39:52 +02007265 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007266 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02007267 char *tmp;
7268
Willy Tarreau3842f002009-06-14 11:39:52 +02007269 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02007270 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007271 for (arg=0; *args[arg+1]; arg++)
7272 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02007273 *tmp = '\0'; // fix the next arg to \0
7274 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007275 }
Willy Tarreau3842f002009-06-14 11:39:52 +02007276 else if (!strcmp(args[0], "default")) {
7277 kwm = KWM_DEF;
7278 for (arg=0; *args[arg+1]; arg++)
7279 args[arg] = args[arg+1]; // shift args after inversion
7280 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007281
William Lallemand0f99e342011-10-12 17:50:54 +02007282 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
7283 strcmp(args[0], "log") != 0) {
7284 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02007285 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007286 }
7287
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007288 /* detect section start */
7289 list_for_each_entry(ics, &sections, list) {
7290 if (strcmp(args[0], ics->section_name) == 0) {
7291 cursection = ics->section_name;
7292 cs = ics;
7293 break;
7294 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007295 }
7296
Willy Tarreaubaaee002006-06-26 02:48:02 +02007297 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007298 if (cs)
7299 err_code |= cs->section_parser(file, linenum, args, kwm);
7300 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007301 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007302 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007303 }
Willy Tarreau058e9072009-07-20 09:30:05 +02007304
7305 if (err_code & ERR_ABORT)
7306 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007307 }
Christopher Faulet79bdef32016-11-04 22:36:15 +01007308 free(cfg_scope);
7309 cfg_scope = NULL;
Willy Tarreau6daf3432008-01-22 16:44:08 +01007310 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02007311 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007312 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02007313 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007314}
7315
Willy Tarreau64ab6072014-09-16 12:17:36 +02007316/* This function propagates processes from frontend <from> to backend <to> so
7317 * that it is always guaranteed that a backend pointed to by a frontend is
7318 * bound to all of its processes. After that, if the target is a "listen"
7319 * instance, the function recursively descends the target's own targets along
Willy Tarreau98d04852015-05-26 12:18:29 +02007320 * default_backend and use_backend rules. Since the bits are
Willy Tarreau64ab6072014-09-16 12:17:36 +02007321 * checked first to ensure that <to> is already bound to all processes of
7322 * <from>, there is no risk of looping and we ensure to follow the shortest
7323 * path to the destination.
7324 *
7325 * It is possible to set <to> to NULL for the first call so that the function
7326 * takes care of visiting the initial frontend in <from>.
7327 *
7328 * It is important to note that the function relies on the fact that all names
7329 * have already been resolved.
7330 */
7331void propagate_processes(struct proxy *from, struct proxy *to)
7332{
7333 struct switching_rule *rule;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007334
7335 if (to) {
7336 /* check whether we need to go down */
7337 if (from->bind_proc &&
7338 (from->bind_proc & to->bind_proc) == from->bind_proc)
7339 return;
7340
7341 if (!from->bind_proc && !to->bind_proc)
7342 return;
7343
7344 to->bind_proc = from->bind_proc ?
7345 (to->bind_proc | from->bind_proc) : 0;
7346
7347 /* now propagate down */
7348 from = to;
7349 }
7350
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01007351 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02007352 return;
7353
Willy Tarreauf6b70012014-12-18 14:00:43 +01007354 if (from->state == PR_STSTOPPED)
7355 return;
7356
Willy Tarreau64ab6072014-09-16 12:17:36 +02007357 /* default_backend */
7358 if (from->defbe.be)
7359 propagate_processes(from, from->defbe.be);
7360
7361 /* use_backend */
7362 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02007363 if (rule->dynamic)
7364 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007365 to = rule->be.backend;
7366 propagate_processes(from, to);
7367 }
Willy Tarreau64ab6072014-09-16 12:17:36 +02007368}
7369
Willy Tarreaubb925012009-07-23 13:36:36 +02007370/*
7371 * Returns the error code, 0 if OK, or any combination of :
7372 * - ERR_ABORT: must abort ASAP
7373 * - ERR_FATAL: we can continue parsing but not start the service
7374 * - ERR_WARN: a warning has been emitted
7375 * - ERR_ALERT: an alert has been emitted
7376 * Only the two first ones can stop processing, the two others are just
7377 * indicators.
7378 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007379int check_config_validity()
7380{
7381 int cfgerr = 0;
7382 struct proxy *curproxy = NULL;
7383 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02007384 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007385 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007386 struct bind_conf *bind_conf;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01007387 char *err;
Baptiste Assmann201c07f2017-05-22 15:17:15 +02007388 struct dns_resolvers *curr_resolvers;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007389
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007390 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007391 /*
7392 * Now, check for the integrity of all that we have collected.
7393 */
7394
7395 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02007396 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007397
Willy Tarreau193b8c62012-11-22 00:17:38 +01007398 if (!global.tune.max_http_hdr)
7399 global.tune.max_http_hdr = MAX_HTTP_HDR;
7400
7401 if (!global.tune.cookie_len)
7402 global.tune.cookie_len = CAPTURE_LEN;
7403
Stéphane Cottin23e9e932017-05-18 08:58:41 +02007404 if (!global.tune.requri_len)
7405 global.tune.requri_len = REQURI_LEN;
7406
Emeric Brun96fd9262017-07-05 13:33:16 +02007407 pool2_requri = create_pool("requri", global.tune.requri_len , MEM_F_SHARED);
7408
Willy Tarreau193b8c62012-11-22 00:17:38 +01007409 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
7410
Baptiste Assmann201c07f2017-05-22 15:17:15 +02007411 /* allocate pool of resolution per resolvers */
7412 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
7413 if (dns_alloc_resolution_pool(curr_resolvers) != 0) {
7414 /* error message is already displayed by dns_alloc_resolution_pool() */
7415 err_code |= ERR_ALERT | ERR_ABORT;
7416 goto out;
7417 }
7418 }
7419
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007420 /* Post initialisation of the users and groups lists. */
7421 err_code = userlist_postinit();
7422 if (err_code != ERR_NONE)
7423 goto out;
7424
Willy Tarreau55bc0f82009-03-15 14:51:53 +01007425 /* first, we will invert the proxy list order */
7426 curproxy = NULL;
7427 while (proxy) {
7428 struct proxy *next;
7429
7430 next = proxy->next;
7431 proxy->next = curproxy;
7432 curproxy = proxy;
7433 if (!next)
7434 break;
7435 proxy = next;
7436 }
7437
Willy Tarreau419ead82014-09-16 13:41:21 +02007438 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007439 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007440 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01007441 struct sticking_rule *mrule;
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007442 struct act_rule *trule;
7443 struct act_rule *hrqrule;
Dragan Dosen1322d092015-09-22 16:05:32 +02007444 struct logsrv *tmplogsrv;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007445 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01007446 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007447
Willy Tarreau050536d2012-10-04 08:47:34 +02007448 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007449 /* proxy ID not set, use automatic numbering with first
7450 * spare entry starting with next_pxid.
7451 */
7452 next_pxid = get_next_id(&used_proxy_id, next_pxid);
7453 curproxy->conf.id.key = curproxy->uuid = next_pxid;
7454 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007455 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007456 next_pxid++;
7457
Willy Tarreau55ea7572007-06-17 19:56:27 +02007458
Willy Tarreaubaaee002006-06-26 02:48:02 +02007459 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02007460 /* ensure we don't keep listeners uselessly bound */
7461 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02007462 free((void *)curproxy->table.peers.name);
7463 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007464 continue;
7465 }
7466
Willy Tarreau102df612014-05-07 23:56:38 +02007467 /* Check multi-process mode compatibility for the current proxy */
7468
7469 if (curproxy->bind_proc) {
7470 /* an explicit bind-process was specified, let's check how many
7471 * processes remain.
7472 */
David Carliere6c39412015-07-02 07:00:17 +00007473 nbproc = my_popcountl(curproxy->bind_proc);
Willy Tarreau102df612014-05-07 23:56:38 +02007474
7475 curproxy->bind_proc &= nbits(global.nbproc);
7476 if (!curproxy->bind_proc && nbproc == 1) {
7477 Warning("Proxy '%s': the process specified on the 'bind-process' directive refers to a process number that is higher than global.nbproc. The proxy has been forced to run on process 1 only.\n", curproxy->id);
7478 curproxy->bind_proc = 1;
7479 }
7480 else if (!curproxy->bind_proc && nbproc > 1) {
7481 Warning("Proxy '%s': all processes specified on the 'bind-process' directive refer to numbers that are all higher than global.nbproc. The directive was ignored and the proxy will run on all processes.\n", curproxy->id);
7482 curproxy->bind_proc = 0;
7483 }
7484 }
7485
Willy Tarreau3d209582014-05-09 17:06:11 +02007486 /* check and reduce the bind-proc of each listener */
7487 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7488 unsigned long mask;
7489
7490 if (!bind_conf->bind_proc)
7491 continue;
7492
7493 mask = nbits(global.nbproc);
7494 if (curproxy->bind_proc)
7495 mask &= curproxy->bind_proc;
7496 /* mask cannot be null here thanks to the previous checks */
7497
David Carliere6c39412015-07-02 07:00:17 +00007498 nbproc = my_popcountl(bind_conf->bind_proc);
Willy Tarreau3d209582014-05-09 17:06:11 +02007499 bind_conf->bind_proc &= mask;
7500
7501 if (!bind_conf->bind_proc && nbproc == 1) {
7502 Warning("Proxy '%s': the process number specified on the 'process' directive of 'bind %s' at [%s:%d] refers to a process not covered by the proxy. This has been fixed by forcing it to run on the proxy's first process only.\n",
7503 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7504 bind_conf->bind_proc = mask & ~(mask - 1);
7505 }
7506 else if (!bind_conf->bind_proc && nbproc > 1) {
7507 Warning("Proxy '%s': the process range specified on the 'process' directive of 'bind %s' at [%s:%d] only refers to processes not covered by the proxy. The directive was ignored so that all of the proxy's processes are used.\n",
7508 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7509 bind_conf->bind_proc = 0;
7510 }
7511 }
7512
Willy Tarreauff01a212009-03-15 13:46:16 +01007513 switch (curproxy->mode) {
7514 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007515 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007516 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007517 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
7518 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007519 cfgerr++;
7520 }
7521
7522 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007523 Warning("config : servers will be ignored for %s '%s'.\n",
7524 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007525 break;
7526
7527 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007528 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007529 break;
7530
7531 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01007532 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01007533 break;
7534 }
7535
Willy Tarreauf3934b82015-08-11 11:36:45 +02007536 if ((curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->conf.listeners)) {
7537 Warning("config : %s '%s' has no 'bind' directive. Please declare it as a backend if this was intended.\n",
7538 proxy_type_str(curproxy), curproxy->id);
7539 err_code |= ERR_WARN;
7540 }
7541
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007542 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007543 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007544 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007545 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
7546 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007547 cfgerr++;
7548 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007549#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007550 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007551 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
7552 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007553 cfgerr++;
7554 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007555#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02007556 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007557 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
7558 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007559 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007560 }
7561 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02007562 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007563 /* If no LB algo is set in a backend, and we're not in
7564 * transparent mode, dispatch mode nor proxy mode, we
7565 * want to use balance roundrobin by default.
7566 */
7567 curproxy->lbprm.algo &= ~BE_LB_ALGO;
7568 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007569 }
7570 }
Willy Tarreau193cf932007-09-17 10:17:23 +02007571
Willy Tarreau1620ec32011-08-06 17:05:02 +02007572 if (curproxy->options & PR_O_DISPATCH)
7573 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
7574 else if (curproxy->options & PR_O_HTTP_PROXY)
7575 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
7576 else if (curproxy->options & PR_O_TRANSP)
7577 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01007578
Willy Tarreau1620ec32011-08-06 17:05:02 +02007579 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
7580 if (curproxy->options & PR_O_DISABLE404) {
7581 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7582 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
7583 err_code |= ERR_WARN;
7584 curproxy->options &= ~PR_O_DISABLE404;
7585 }
7586 if (curproxy->options2 & PR_O2_CHK_SNDST) {
7587 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7588 "send-state", proxy_type_str(curproxy), curproxy->id);
7589 err_code |= ERR_WARN;
7590 curproxy->options &= ~PR_O2_CHK_SNDST;
7591 }
Willy Tarreauef781042010-01-27 11:53:01 +01007592 }
7593
Simon Horman98637e52014-06-20 12:30:16 +09007594 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
7595 if (!global.external_check) {
7596 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
7597 curproxy->id, "option external-check");
7598 cfgerr++;
7599 }
7600 if (!curproxy->check_command) {
7601 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
7602 curproxy->id, "option external-check");
7603 cfgerr++;
7604 }
7605 }
7606
Simon Horman64e34162015-02-06 11:11:57 +09007607 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007608 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
7609 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Pieter Baauw8669e972015-08-17 00:45:05 +02007610 "'email-alert from', 'email-alert level' 'email-alert mailers', "
7611 "'email-alert myhostname', or 'email-alert to' "
7612 "requires each of 'email-alert from', 'email-alert mailers' and 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007613 "to be present).\n",
7614 proxy_type_str(curproxy), curproxy->id);
7615 err_code |= ERR_WARN;
7616 free_email_alert(curproxy);
7617 }
7618 if (!curproxy->email_alert.myhostname)
Cyril Bontée22bfd62015-12-04 03:07:07 +01007619 curproxy->email_alert.myhostname = strdup(hostname);
Simon Horman9dc49962015-01-30 11:22:59 +09007620 }
7621
Simon Horman98637e52014-06-20 12:30:16 +09007622 if (curproxy->check_command) {
7623 int clear = 0;
7624 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7625 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7626 "external-check command", proxy_type_str(curproxy), curproxy->id);
7627 err_code |= ERR_WARN;
7628 clear = 1;
7629 }
7630 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
Ben Cabot49795eb2015-09-16 12:07:51 +01007631 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-check path' is not set.\n",
Simon Horman98637e52014-06-20 12:30:16 +09007632 curproxy->id, "external-check command");
7633 cfgerr++;
7634 }
7635 if (clear) {
7636 free(curproxy->check_command);
7637 curproxy->check_command = NULL;
7638 }
7639 }
7640
7641 if (curproxy->check_path) {
7642 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7643 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7644 "external-check path", proxy_type_str(curproxy), curproxy->id);
7645 err_code |= ERR_WARN;
7646 free(curproxy->check_path);
7647 curproxy->check_path = NULL;
7648 }
7649 }
7650
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007651 /* if a default backend was specified, let's find it */
7652 if (curproxy->defbe.name) {
7653 struct proxy *target;
7654
Willy Tarreauafb39922015-05-26 12:04:09 +02007655 target = proxy_be_by_name(curproxy->defbe.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007656 if (!target) {
7657 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
7658 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007659 cfgerr++;
7660 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007661 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
7662 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02007663 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007664 } else if (target->mode != curproxy->mode &&
7665 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7666
7667 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) as its default backend (see 'mode').\n",
7668 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7669 curproxy->conf.file, curproxy->conf.line,
7670 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7671 target->conf.file, target->conf.line);
7672 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007673 } else {
7674 free(curproxy->defbe.name);
7675 curproxy->defbe.be = target;
Emeric Brun3f783572017-01-12 11:21:28 +01007676 /* Update tot_fe_maxconn for a further fullconn's computation */
7677 target->tot_fe_maxconn += curproxy->maxconn;
Willy Tarreauff678132012-02-13 14:32:34 +01007678 /* Emit a warning if this proxy also has some servers */
7679 if (curproxy->srv) {
7680 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
7681 curproxy->id);
7682 err_code |= ERR_WARN;
7683 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007684 }
7685 }
7686
Emeric Brun3f783572017-01-12 11:21:28 +01007687 if (!curproxy->defbe.be && (curproxy->cap & PR_CAP_LISTEN) == PR_CAP_LISTEN) {
7688 /* Case of listen without default backend
7689 * The curproxy will be its own default backend
7690 * so we update tot_fe_maxconn for a further
7691 * fullconn's computation */
7692 curproxy->tot_fe_maxconn += curproxy->maxconn;
7693 }
7694
Willy Tarreau55ea7572007-06-17 19:56:27 +02007695 /* find the target proxy for 'use_backend' rules */
7696 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007697 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007698 struct logformat_node *node;
7699 char *pxname;
7700
7701 /* Try to parse the string as a log format expression. If the result
7702 * of the parsing is only one entry containing a simple string, then
7703 * it's a standard string corresponding to a static rule, thus the
7704 * parsing is cancelled and be.name is restored to be resolved.
7705 */
7706 pxname = rule->be.name;
7707 LIST_INIT(&rule->be.expr);
Thierry FOURNIER / OZON.IO4ed1c952016-11-24 23:57:54 +01007708 curproxy->conf.args.ctx = ARGC_UBK;
7709 curproxy->conf.args.file = rule->file;
7710 curproxy->conf.args.line = rule->line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01007711 err = NULL;
7712 if (!parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR, &err)) {
7713 Alert("Parsing [%s:%d]: failed to parse use_backend rule '%s' : %s.\n",
7714 rule->file, rule->line, pxname, err);
7715 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01007716 cfgerr++;
7717 continue;
7718 }
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007719 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
7720
7721 if (!LIST_ISEMPTY(&rule->be.expr)) {
7722 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
7723 rule->dynamic = 1;
7724 free(pxname);
7725 continue;
7726 }
7727 /* simple string: free the expression and fall back to static rule */
7728 free(node->arg);
7729 free(node);
7730 }
7731
7732 rule->dynamic = 0;
7733 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007734
Willy Tarreauafb39922015-05-26 12:04:09 +02007735 target = proxy_be_by_name(rule->be.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007736 if (!target) {
7737 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
7738 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007739 cfgerr++;
7740 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007741 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
7742 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007743 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007744 } else if (target->mode != curproxy->mode &&
7745 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7746
7747 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) in a 'use_backend' rule (see 'mode').\n",
7748 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7749 curproxy->conf.file, curproxy->conf.line,
7750 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7751 target->conf.file, target->conf.line);
7752 cfgerr++;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007753 } else {
7754 free((void *)rule->be.name);
7755 rule->be.backend = target;
Emeric Brun3f783572017-01-12 11:21:28 +01007756 /* For each target of switching rules, we update
7757 * their tot_fe_maxconn, except if a previous rule point
7758 * on the same backend or on the default backend */
7759 if (rule->be.backend != curproxy->defbe.be) {
7760 struct switching_rule *swrule;
7761
7762 list_for_each_entry(swrule, &curproxy->switching_rules, list) {
7763 if (rule == swrule) {
7764 target->tot_fe_maxconn += curproxy->maxconn;
7765 break;
7766 }
7767 else if (!swrule->dynamic && swrule->be.backend == rule->be.backend) {
7768 /* there is multiple ref of this backend */
7769 break;
7770 }
7771 }
7772 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02007773 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007774 }
7775
Willy Tarreau64ab6072014-09-16 12:17:36 +02007776 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007777 list_for_each_entry(srule, &curproxy->server_rules, list) {
7778 struct server *target = findserver(curproxy, srule->srv.name);
7779
7780 if (!target) {
7781 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7782 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7783 cfgerr++;
7784 continue;
7785 }
7786 free((void *)srule->srv.name);
7787 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007788 }
7789
Emeric Brunb982a3d2010-01-04 15:45:53 +01007790 /* find the target table for 'stick' rules */
7791 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7792 struct proxy *target;
7793
Emeric Brun1d33b292010-01-04 15:47:17 +01007794 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7795 if (mrule->flags & STK_IS_STORE)
7796 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7797
Emeric Brunb982a3d2010-01-04 15:45:53 +01007798 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007799 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007800 else
7801 target = curproxy;
7802
7803 if (!target) {
7804 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7805 curproxy->id, mrule->table.name);
7806 cfgerr++;
7807 }
7808 else if (target->table.size == 0) {
7809 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7810 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7811 cfgerr++;
7812 }
Willy Tarreau12785782012-04-27 21:37:17 +02007813 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7814 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007815 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7816 cfgerr++;
7817 }
7818 else {
7819 free((void *)mrule->table.name);
7820 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007821 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007822 }
7823 }
7824
7825 /* find the target table for 'store response' rules */
7826 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7827 struct proxy *target;
7828
Emeric Brun1d33b292010-01-04 15:47:17 +01007829 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7830
Emeric Brunb982a3d2010-01-04 15:45:53 +01007831 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007832 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007833 else
7834 target = curproxy;
7835
7836 if (!target) {
7837 Alert("Proxy '%s': unable to find store table '%s'.\n",
7838 curproxy->id, mrule->table.name);
7839 cfgerr++;
7840 }
7841 else if (target->table.size == 0) {
7842 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7843 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7844 cfgerr++;
7845 }
Willy Tarreau12785782012-04-27 21:37:17 +02007846 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7847 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007848 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7849 cfgerr++;
7850 }
7851 else {
7852 free((void *)mrule->table.name);
7853 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007854 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007855 }
7856 }
7857
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007858 /* find the target table for 'tcp-request' layer 4 rules */
7859 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
7860 struct proxy *target;
7861
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007862 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007863 continue;
7864
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007865 if (trule->arg.trk_ctr.table.n)
7866 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007867 else
7868 target = curproxy;
7869
7870 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007871 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007872 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007873 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007874 cfgerr++;
7875 }
7876 else if (target->table.size == 0) {
7877 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007878 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007879 cfgerr++;
7880 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007881 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007882 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007883 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007884 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007885 cfgerr++;
7886 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007887 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007888 free(trule->arg.trk_ctr.table.n);
7889 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007890 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007891 * to pass a list of counters to track and allocate them right here using
7892 * stktable_alloc_data_type().
7893 */
7894 }
7895 }
7896
Willy Tarreau620408f2016-10-21 16:37:51 +02007897 /* find the target table for 'tcp-request' layer 5 rules */
7898 list_for_each_entry(trule, &curproxy->tcp_req.l5_rules, list) {
7899 struct proxy *target;
7900
7901 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
7902 continue;
7903
7904 if (trule->arg.trk_ctr.table.n)
7905 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
7906 else
7907 target = curproxy;
7908
7909 if (!target) {
7910 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7911 curproxy->id, trule->arg.trk_ctr.table.n,
7912 tcp_trk_idx(trule->action));
7913 cfgerr++;
7914 }
7915 else if (target->table.size == 0) {
7916 Alert("Proxy '%s': table '%s' used but not configured.\n",
7917 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
7918 cfgerr++;
7919 }
7920 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
7921 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7922 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
7923 tcp_trk_idx(trule->action));
7924 cfgerr++;
7925 }
7926 else {
7927 free(trule->arg.trk_ctr.table.n);
7928 trule->arg.trk_ctr.table.t = &target->table;
7929 /* Note: if we decide to enhance the track-sc syntax, we may be able
7930 * to pass a list of counters to track and allocate them right here using
7931 * stktable_alloc_data_type().
7932 */
7933 }
7934 }
7935
Willy Tarreaud1f96522010-08-03 19:34:32 +02007936 /* find the target table for 'tcp-request' layer 6 rules */
7937 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7938 struct proxy *target;
7939
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007940 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02007941 continue;
7942
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007943 if (trule->arg.trk_ctr.table.n)
7944 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007945 else
7946 target = curproxy;
7947
7948 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007949 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007950 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007951 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02007952 cfgerr++;
7953 }
7954 else if (target->table.size == 0) {
7955 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007956 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007957 cfgerr++;
7958 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007959 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007960 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007961 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007962 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007963 cfgerr++;
7964 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02007965 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007966 free(trule->arg.trk_ctr.table.n);
7967 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007968 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02007969 * to pass a list of counters to track and allocate them right here using
7970 * stktable_alloc_data_type().
7971 */
7972 }
7973 }
7974
Baptiste Assmanne9544932015-11-03 23:31:35 +01007975 /* parse http-request capture rules to ensure id really exists */
7976 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7977 if (hrqrule->action != ACT_CUSTOM ||
7978 hrqrule->action_ptr != http_action_req_capture_by_id)
7979 continue;
7980
7981 if (hrqrule->arg.capid.idx >= curproxy->nb_req_cap) {
7982 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-request capture rule.\n",
7983 curproxy->id, hrqrule->arg.capid.idx);
7984 cfgerr++;
7985 }
7986 }
7987
7988 /* parse http-response capture rules to ensure id really exists */
7989 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
7990 if (hrqrule->action != ACT_CUSTOM ||
7991 hrqrule->action_ptr != http_action_res_capture_by_id)
7992 continue;
7993
7994 if (hrqrule->arg.capid.idx >= curproxy->nb_rsp_cap) {
7995 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-response capture rule.\n",
7996 curproxy->id, hrqrule->arg.capid.idx);
7997 cfgerr++;
7998 }
7999 }
8000
Willy Tarreau09448f72014-06-25 18:12:15 +02008001 /* find the target table for 'http-request' layer 7 rules */
8002 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
8003 struct proxy *target;
8004
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008005 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau09448f72014-06-25 18:12:15 +02008006 continue;
8007
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008008 if (hrqrule->arg.trk_ctr.table.n)
8009 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
Willy Tarreau09448f72014-06-25 18:12:15 +02008010 else
8011 target = curproxy;
8012
8013 if (!target) {
8014 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008015 curproxy->id, hrqrule->arg.trk_ctr.table.n,
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08008016 http_trk_idx(hrqrule->action));
Willy Tarreau09448f72014-06-25 18:12:15 +02008017 cfgerr++;
8018 }
8019 else if (target->table.size == 0) {
8020 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008021 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau09448f72014-06-25 18:12:15 +02008022 cfgerr++;
8023 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008024 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau09448f72014-06-25 18:12:15 +02008025 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008026 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08008027 http_trk_idx(hrqrule->action));
8028 cfgerr++;
8029 }
8030 else {
8031 free(hrqrule->arg.trk_ctr.table.n);
8032 hrqrule->arg.trk_ctr.table.t = &target->table;
8033 /* Note: if we decide to enhance the track-sc syntax, we may be able
8034 * to pass a list of counters to track and allocate them right here using
8035 * stktable_alloc_data_type().
8036 */
8037 }
8038 }
8039
8040 /* find the target table for 'http-response' layer 7 rules */
8041 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
8042 struct proxy *target;
8043
8044 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
8045 continue;
8046
8047 if (hrqrule->arg.trk_ctr.table.n)
8048 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
8049 else
8050 target = curproxy;
8051
8052 if (!target) {
8053 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
8054 curproxy->id, hrqrule->arg.trk_ctr.table.n,
8055 http_trk_idx(hrqrule->action));
8056 cfgerr++;
8057 }
8058 else if (target->table.size == 0) {
8059 Alert("Proxy '%s': table '%s' used but not configured.\n",
8060 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
8061 cfgerr++;
8062 }
8063 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
8064 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
8065 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
8066 http_trk_idx(hrqrule->action));
Willy Tarreau09448f72014-06-25 18:12:15 +02008067 cfgerr++;
8068 }
8069 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008070 free(hrqrule->arg.trk_ctr.table.n);
8071 hrqrule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau09448f72014-06-25 18:12:15 +02008072 /* Note: if we decide to enhance the track-sc syntax, we may be able
8073 * to pass a list of counters to track and allocate them right here using
8074 * stktable_alloc_data_type().
8075 */
8076 }
8077 }
8078
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02008079 /* move any "block" rules at the beginning of the http-request rules */
8080 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
8081 /* insert block_rules into http_req_rules at the beginning */
8082 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
8083 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
8084 curproxy->block_rules.n->p = &curproxy->http_req_rules;
8085 curproxy->http_req_rules.n = curproxy->block_rules.n;
8086 LIST_INIT(&curproxy->block_rules);
8087 }
8088
Emeric Brun32da3c42010-09-23 18:39:19 +02008089 if (curproxy->table.peers.name) {
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02008090 struct peers *curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02008091
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02008092 for (curpeers = cfg_peers; curpeers; curpeers = curpeers->next) {
Emeric Brun32da3c42010-09-23 18:39:19 +02008093 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
8094 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01008095 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02008096 break;
8097 }
8098 }
8099
8100 if (!curpeers) {
8101 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
8102 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02008103 free((void *)curproxy->table.peers.name);
8104 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02008105 cfgerr++;
8106 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008107 else if (curpeers->state == PR_STSTOPPED) {
8108 /* silently disable this peers section */
8109 curproxy->table.peers.p = NULL;
8110 }
Emeric Brun32da3c42010-09-23 18:39:19 +02008111 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02008112 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
8113 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02008114 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02008115 cfgerr++;
8116 }
8117 }
8118
Simon Horman9dc49962015-01-30 11:22:59 +09008119
8120 if (curproxy->email_alert.mailers.name) {
8121 struct mailers *curmailers = mailers;
8122
8123 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
8124 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
8125 free(curproxy->email_alert.mailers.name);
8126 curproxy->email_alert.mailers.m = curmailers;
8127 curmailers->users++;
8128 break;
8129 }
8130 }
8131
8132 if (!curmailers) {
8133 Alert("Proxy '%s': unable to find mailers '%s'.\n",
8134 curproxy->id, curproxy->email_alert.mailers.name);
8135 free_email_alert(curproxy);
8136 cfgerr++;
8137 }
8138 }
8139
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008140 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01008141 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008142 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
8143 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
8144 "proxy", curproxy->id);
8145 cfgerr++;
8146 goto out_uri_auth_compat;
8147 }
8148
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008149 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008150 const char *uri_auth_compat_req[10];
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02008151 struct act_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01008152 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008153
Willy Tarreau95fa4692010-02-01 13:05:50 +01008154 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
8155 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008156
8157 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008158 uri_auth_compat_req[i++] = "realm";
8159 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
8160 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008161
Willy Tarreau95fa4692010-02-01 13:05:50 +01008162 uri_auth_compat_req[i++] = "unless";
8163 uri_auth_compat_req[i++] = "{";
8164 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
8165 uri_auth_compat_req[i++] = "}";
8166 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008167
Willy Tarreauff011f22011-01-06 17:51:27 +01008168 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
8169 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008170 cfgerr++;
8171 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008172 }
8173
Willy Tarreauff011f22011-01-06 17:51:27 +01008174 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01008175
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008176 if (curproxy->uri_auth->auth_realm) {
8177 free(curproxy->uri_auth->auth_realm);
8178 curproxy->uri_auth->auth_realm = NULL;
8179 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008180
8181 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008182 }
8183out_uri_auth_compat:
8184
Dragan Dosen43885c72015-10-01 13:18:13 +02008185 /* check whether we have a log server that uses RFC5424 log format */
Dragan Dosen1322d092015-09-22 16:05:32 +02008186 list_for_each_entry(tmplogsrv, &curproxy->logsrvs, list) {
Dragan Dosen43885c72015-10-01 13:18:13 +02008187 if (tmplogsrv->format == LOG_FORMAT_RFC5424) {
8188 if (!curproxy->conf.logformat_sd_string) {
8189 /* set the default logformat_sd_string */
8190 curproxy->conf.logformat_sd_string = default_rfc5424_sd_log_format;
8191 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008192 break;
Dragan Dosen1322d092015-09-22 16:05:32 +02008193 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008194 }
Dragan Dosen68d2e3a2015-09-19 22:35:44 +02008195
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008196 /* compile the log format */
8197 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02008198 if (curproxy->conf.logformat_string != default_http_log_format &&
8199 curproxy->conf.logformat_string != default_tcp_log_format &&
8200 curproxy->conf.logformat_string != clf_http_log_format)
8201 free(curproxy->conf.logformat_string);
8202 curproxy->conf.logformat_string = NULL;
8203 free(curproxy->conf.lfs_file);
8204 curproxy->conf.lfs_file = NULL;
8205 curproxy->conf.lfs_line = 0;
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008206
8207 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
8208 free(curproxy->conf.logformat_sd_string);
8209 curproxy->conf.logformat_sd_string = NULL;
8210 free(curproxy->conf.lfsd_file);
8211 curproxy->conf.lfsd_file = NULL;
8212 curproxy->conf.lfsd_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008213 }
8214
Willy Tarreau62a61232013-04-12 18:13:46 +02008215 if (curproxy->conf.logformat_string) {
8216 curproxy->conf.args.ctx = ARGC_LOG;
8217 curproxy->conf.args.file = curproxy->conf.lfs_file;
8218 curproxy->conf.args.line = curproxy->conf.lfs_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008219 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008220 if (!parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008221 SMP_VAL_FE_LOG_END, &err)) {
8222 Alert("Parsing [%s:%d]: failed to parse log-format : %s.\n",
8223 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8224 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008225 cfgerr++;
8226 }
Willy Tarreau62a61232013-04-12 18:13:46 +02008227 curproxy->conf.args.file = NULL;
8228 curproxy->conf.args.line = 0;
8229 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008230
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008231 if (curproxy->conf.logformat_sd_string) {
8232 curproxy->conf.args.ctx = ARGC_LOGSD;
8233 curproxy->conf.args.file = curproxy->conf.lfsd_file;
8234 curproxy->conf.args.line = curproxy->conf.lfsd_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008235 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008236 if (!parse_logformat_string(curproxy->conf.logformat_sd_string, curproxy, &curproxy->logformat_sd, LOG_OPT_MANDATORY,
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008237 SMP_VAL_FE_LOG_END, &err)) {
8238 Alert("Parsing [%s:%d]: failed to parse log-format-sd : %s.\n",
8239 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8240 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008241 cfgerr++;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008242 } else if (!add_to_logformat_list(NULL, NULL, LF_SEPARATOR, &curproxy->logformat_sd, &err)) {
8243 Alert("Parsing [%s:%d]: failed to parse log-format-sd : %s.\n",
8244 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8245 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008246 cfgerr++;
8247 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008248 curproxy->conf.args.file = NULL;
8249 curproxy->conf.args.line = 0;
8250 }
8251
Willy Tarreau62a61232013-04-12 18:13:46 +02008252 if (curproxy->conf.uniqueid_format_string) {
8253 curproxy->conf.args.ctx = ARGC_UIF;
8254 curproxy->conf.args.file = curproxy->conf.uif_file;
8255 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008256 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008257 if (!parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008258 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR, &err)) {
8259 Alert("Parsing [%s:%d]: failed to parse unique-id : %s.\n",
8260 curproxy->conf.uif_file, curproxy->conf.uif_line, err);
8261 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008262 cfgerr++;
8263 }
Willy Tarreau62a61232013-04-12 18:13:46 +02008264 curproxy->conf.args.file = NULL;
8265 curproxy->conf.args.line = 0;
8266 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008267
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01008268 /* only now we can check if some args remain unresolved.
8269 * This must be done after the users and groups resolution.
8270 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008271 cfgerr += smp_resolve_args(curproxy);
8272 if (!cfgerr)
8273 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01008274
Willy Tarreau2738a142006-07-08 17:28:09 +02008275 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008276 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02008277 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02008278 (!curproxy->timeout.connect ||
8279 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008280 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02008281 " | While not properly invalid, you will certainly encounter various problems\n"
8282 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01008283 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008284 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008285 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02008286 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02008287
Willy Tarreau1fa31262007-12-03 00:36:16 +01008288 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
8289 * We must still support older configurations, so let's find out whether those
8290 * parameters have been set or must be copied from contimeouts.
8291 */
8292 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008293 if (!curproxy->timeout.tarpit ||
8294 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008295 /* tarpit timeout not set. We search in the following order:
8296 * default.tarpit, curr.connect, default.connect.
8297 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008298 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008299 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008300 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008301 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008302 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008303 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008304 }
8305 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008306 (!curproxy->timeout.queue ||
8307 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008308 /* queue timeout not set. We search in the following order:
8309 * default.queue, curr.connect, default.connect.
8310 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008311 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008312 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008313 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008314 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008315 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008316 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008317 }
8318 }
8319
Willy Tarreau1620ec32011-08-06 17:05:02 +02008320 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01008321 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02008322 curproxy->check_req = malloc(curproxy->check_len);
Willy Tarreau137325d2010-02-01 16:38:17 +01008323 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02008324 }
8325
Willy Tarreau215663d2014-06-13 18:30:23 +02008326 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
8327 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
8328 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
8329 proxy_type_str(curproxy), curproxy->id);
8330 err_code |= ERR_WARN;
8331 }
8332
Willy Tarreau193b8c62012-11-22 00:17:38 +01008333 /* ensure that cookie capture length is not too large */
8334 if (curproxy->capture_len >= global.tune.cookie_len) {
8335 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
8336 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
8337 err_code |= ERR_WARN;
8338 curproxy->capture_len = global.tune.cookie_len - 1;
8339 }
8340
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008341 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01008342 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008343 curproxy->req_cap_pool = create_pool("ptrcap",
8344 curproxy->nb_req_cap * sizeof(char *),
8345 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008346 }
8347
8348 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008349 curproxy->rsp_cap_pool = create_pool("ptrcap",
8350 curproxy->nb_rsp_cap * sizeof(char *),
8351 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008352 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008353
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02008354 switch (curproxy->load_server_state_from_file) {
8355 case PR_SRV_STATE_FILE_UNSPEC:
8356 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
8357 break;
8358 case PR_SRV_STATE_FILE_GLOBAL:
8359 if (!global.server_state_file) {
8360 Warning("config : backend '%s' configured to load server state file from global section 'server-state-file' directive. Unfortunately, 'server-state-file' is not set!\n",
8361 curproxy->id);
8362 err_code |= ERR_WARN;
8363 }
8364 break;
8365 }
8366
Willy Tarreaubaaee002006-06-26 02:48:02 +02008367 /* first, we will invert the servers list order */
8368 newsrv = NULL;
8369 while (curproxy->srv) {
8370 struct server *next;
8371
8372 next = curproxy->srv->next;
8373 curproxy->srv->next = newsrv;
8374 newsrv = curproxy->srv;
8375 if (!next)
8376 break;
8377 curproxy->srv = next;
8378 }
8379
Willy Tarreau17edc812014-01-03 12:14:34 +01008380 /* Check that no server name conflicts. This causes trouble in the stats.
8381 * We only emit a warning for the first conflict affecting each server,
8382 * in order to avoid combinatory explosion if all servers have the same
8383 * name. We do that only for servers which do not have an explicit ID,
8384 * because these IDs were made also for distinguishing them and we don't
8385 * want to annoy people who correctly manage them.
8386 */
8387 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
8388 struct server *other_srv;
8389
8390 if (newsrv->puid)
8391 continue;
8392
8393 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
8394 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
8395 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
8396 newsrv->conf.file, newsrv->conf.line,
8397 proxy_type_str(curproxy), curproxy->id,
8398 newsrv->id, other_srv->conf.line);
8399 break;
8400 }
8401 }
8402 }
8403
Willy Tarreaudd701652010-05-25 23:03:02 +02008404 /* assign automatic UIDs to servers which don't have one yet */
8405 next_id = 1;
8406 newsrv = curproxy->srv;
8407 while (newsrv != NULL) {
8408 if (!newsrv->puid) {
8409 /* server ID not set, use automatic numbering with first
8410 * spare entry starting with next_svid.
8411 */
8412 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
8413 newsrv->conf.id.key = newsrv->puid = next_id;
8414 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
8415 }
8416 next_id++;
8417 newsrv = newsrv->next;
8418 }
8419
Willy Tarreau20697042007-11-15 23:26:18 +01008420 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01008421 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02008422
Willy Tarreau62c3be22012-01-20 13:12:32 +01008423 /*
8424 * If this server supports a maxconn parameter, it needs a dedicated
8425 * tasks to fill the emptied slots when a connection leaves.
8426 * Also, resolve deferred tracking dependency if needed.
8427 */
8428 newsrv = curproxy->srv;
8429 while (newsrv != NULL) {
8430 if (newsrv->minconn > newsrv->maxconn) {
8431 /* Only 'minconn' was specified, or it was higher than or equal
8432 * to 'maxconn'. Let's turn this into maxconn and clean it, as
8433 * this will avoid further useless expensive computations.
8434 */
8435 newsrv->maxconn = newsrv->minconn;
8436 } else if (newsrv->maxconn && !newsrv->minconn) {
8437 /* minconn was not specified, so we set it to maxconn */
8438 newsrv->minconn = newsrv->maxconn;
8439 }
8440
Willy Tarreau17d45382016-12-22 21:16:08 +01008441 /* this will also properly set the transport layer for prod and checks */
8442 if (newsrv->use_ssl || newsrv->check.use_ssl) {
8443 if (xprt_get(XPRT_SSL) && xprt_get(XPRT_SSL)->prepare_srv)
8444 cfgerr += xprt_get(XPRT_SSL)->prepare_srv(newsrv);
8445 }
Emeric Brun94324a42012-10-11 14:00:19 +02008446
Willy Tarreau2f075e92013-12-03 11:11:34 +01008447 /* set the check type on the server */
8448 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
8449
Willy Tarreau62c3be22012-01-20 13:12:32 +01008450 if (newsrv->trackit) {
8451 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02008452 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008453 char *pname, *sname;
8454
8455 pname = newsrv->trackit;
8456 sname = strrchr(pname, '/');
8457
8458 if (sname)
8459 *sname++ = '\0';
8460 else {
8461 sname = pname;
8462 pname = NULL;
8463 }
8464
8465 if (pname) {
Willy Tarreau9e0bb102015-05-26 11:24:42 +02008466 px = proxy_be_by_name(pname);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008467 if (!px) {
8468 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
8469 proxy_type_str(curproxy), curproxy->id,
8470 newsrv->id, pname);
8471 cfgerr++;
8472 goto next_srv;
8473 }
8474 } else
8475 px = curproxy;
8476
8477 srv = findserver(px, sname);
8478 if (!srv) {
8479 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
8480 proxy_type_str(curproxy), curproxy->id,
8481 newsrv->id, sname);
8482 cfgerr++;
8483 goto next_srv;
8484 }
8485
Willy Tarreau32091232014-05-16 13:52:00 +02008486 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
8487 !(srv->agent.state & CHK_ST_CONFIGURED) &&
8488 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01008489 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02008490 "tracking as it does not have any check nor agent enabled.\n",
8491 proxy_type_str(curproxy), curproxy->id,
8492 newsrv->id, px->id, srv->id);
8493 cfgerr++;
8494 goto next_srv;
8495 }
8496
8497 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
8498
Frédéric Lécaille2efc6492017-03-14 14:32:17 +01008499 if (newsrv == srv || loop) {
Willy Tarreau32091232014-05-16 13:52:00 +02008500 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
8501 "belongs to a tracking chain looping back to %s/%s.\n",
8502 proxy_type_str(curproxy), curproxy->id,
Frédéric Lécaille2efc6492017-03-14 14:32:17 +01008503 newsrv->id, px->id, srv->id, px->id,
8504 newsrv == srv ? srv->id : loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008505 cfgerr++;
8506 goto next_srv;
8507 }
8508
8509 if (curproxy != px &&
8510 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
8511 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
8512 "tracking: disable-on-404 option inconsistency.\n",
8513 proxy_type_str(curproxy), curproxy->id,
8514 newsrv->id, px->id, srv->id);
8515 cfgerr++;
8516 goto next_srv;
8517 }
8518
Willy Tarreau62c3be22012-01-20 13:12:32 +01008519 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01008520 newsrv->tracknext = srv->trackers;
8521 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008522
8523 free(newsrv->trackit);
8524 newsrv->trackit = NULL;
8525 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008526
8527 /*
8528 * resolve server's resolvers name and update the resolvers pointer
8529 * accordingly
8530 */
8531 if (newsrv->resolvers_id) {
8532 struct dns_resolvers *curr_resolvers;
8533 int found;
8534
8535 found = 0;
8536 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
8537 if (!strcmp(curr_resolvers->id, newsrv->resolvers_id)) {
8538 found = 1;
8539 break;
8540 }
8541 }
8542
8543 if (!found) {
8544 Alert("config : %s '%s', server '%s': unable to find required resolvers '%s'\n",
8545 proxy_type_str(curproxy), curproxy->id,
8546 newsrv->id, newsrv->resolvers_id);
8547 cfgerr++;
8548 } else {
Baptiste Assmann201c07f2017-05-22 15:17:15 +02008549 if (newsrv->hostname_dn) {
Baptiste Assmann42746372017-05-03 12:12:02 +02008550 newsrv->resolvers = curr_resolvers;
Baptiste Assmann201c07f2017-05-22 15:17:15 +02008551 if (dns_link_resolution(newsrv, OBJ_TYPE_SERVER, NULL) != 0) {
8552 Alert("config : %s '%s', server '%s': unable to set DNS resolution\n",
8553 proxy_type_str(curproxy), curproxy->id,
8554 newsrv->id);
8555 cfgerr++;
8556 }
8557 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008558 }
8559 }
8560 else {
8561 /* if no resolvers section associated to this server
8562 * we can clean up the associated resolution structure
8563 */
8564 if (newsrv->resolution) {
8565 free(newsrv->resolution->hostname_dn);
8566 newsrv->resolution->hostname_dn = NULL;
8567 free(newsrv->resolution);
8568 newsrv->resolution = NULL;
8569 }
8570 }
8571
Willy Tarreau62c3be22012-01-20 13:12:32 +01008572 next_srv:
8573 newsrv = newsrv->next;
8574 }
8575
Olivier Houchard4e694042017-03-14 20:01:29 +01008576 /*
8577 * Try to generate dynamic cookies for servers now.
8578 * It couldn't be done earlier, since at the time we parsed
8579 * the server line, we may not have known yet that we
8580 * should use dynamic cookies, or the secret key may not
8581 * have been provided yet.
8582 */
8583 if (curproxy->ck_opts & PR_CK_DYNAMIC) {
8584 newsrv = curproxy->srv;
8585 while (newsrv != NULL) {
8586 srv_set_dyncookie(newsrv);
8587 newsrv = newsrv->next;
8588 }
8589
8590 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008591 /* We have to initialize the server lookup mechanism depending
8592 * on what LB algorithm was choosen.
8593 */
8594
8595 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
8596 switch (curproxy->lbprm.algo & BE_LB_KIND) {
8597 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02008598 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
8599 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8600 init_server_map(curproxy);
8601 } else {
8602 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
8603 fwrr_init_server_groups(curproxy);
8604 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008605 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008606
Willy Tarreau3ebb1162012-02-13 16:57:44 +01008607 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01008608 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
8609 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
8610 fwlc_init_server_tree(curproxy);
8611 } else {
8612 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
8613 fas_init_server_tree(curproxy);
8614 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008615 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008616
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008617 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008618 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
8619 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
8620 chash_init_server_tree(curproxy);
8621 } else {
8622 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8623 init_server_map(curproxy);
8624 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008625 break;
8626 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02008627
8628 if (curproxy->options & PR_O_LOGASAP)
8629 curproxy->to_log &= ~LW_BYTES;
8630
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008631 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008632 (curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->logsrvs) &&
8633 (!LIST_ISEMPTY(&curproxy->logformat) || !LIST_ISEMPTY(&curproxy->logformat_sd))) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008634 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
8635 proxy_type_str(curproxy), curproxy->id);
8636 err_code |= ERR_WARN;
8637 }
8638
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008639 if (curproxy->mode != PR_MODE_HTTP) {
8640 int optnum;
8641
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008642 if (curproxy->uri_auth) {
8643 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
8644 proxy_type_str(curproxy), curproxy->id);
8645 err_code |= ERR_WARN;
8646 curproxy->uri_auth = NULL;
8647 }
8648
Willy Tarreaude7dc882017-03-10 11:49:21 +01008649 if (curproxy->capture_name) {
8650 Warning("config : 'capture' statement ignored for %s '%s' as it requires HTTP mode.\n",
8651 proxy_type_str(curproxy), curproxy->id);
8652 err_code |= ERR_WARN;
8653 }
8654
8655 if (!LIST_ISEMPTY(&curproxy->http_req_rules)) {
8656 Warning("config : 'http-request' rules ignored for %s '%s' as they require HTTP mode.\n",
8657 proxy_type_str(curproxy), curproxy->id);
8658 err_code |= ERR_WARN;
8659 }
8660
8661 if (!LIST_ISEMPTY(&curproxy->http_res_rules)) {
8662 Warning("config : 'http-response' rules ignored for %s '%s' as they require HTTP mode.\n",
8663 proxy_type_str(curproxy), curproxy->id);
8664 err_code |= ERR_WARN;
8665 }
8666
8667 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
8668 Warning("config : 'block' rules ignored for %s '%s' as they require HTTP mode.\n",
8669 proxy_type_str(curproxy), curproxy->id);
8670 err_code |= ERR_WARN;
8671 }
8672
8673 if (!LIST_ISEMPTY(&curproxy->redirect_rules)) {
8674 Warning("config : 'redirect' rules ignored for %s '%s' as they require HTTP mode.\n",
8675 proxy_type_str(curproxy), curproxy->id);
8676 err_code |= ERR_WARN;
8677 }
8678
Willy Tarreau87cf5142011-08-19 22:57:24 +02008679 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008680 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8681 "forwardfor", proxy_type_str(curproxy), curproxy->id);
8682 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02008683 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008684 }
8685
8686 if (curproxy->options & PR_O_ORGTO) {
8687 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8688 "originalto", proxy_type_str(curproxy), curproxy->id);
8689 err_code |= ERR_WARN;
8690 curproxy->options &= ~PR_O_ORGTO;
8691 }
8692
8693 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
8694 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
8695 (curproxy->cap & cfg_opts[optnum].cap) &&
8696 (curproxy->options & cfg_opts[optnum].val)) {
8697 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8698 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
8699 err_code |= ERR_WARN;
8700 curproxy->options &= ~cfg_opts[optnum].val;
8701 }
8702 }
8703
8704 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
8705 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
8706 (curproxy->cap & cfg_opts2[optnum].cap) &&
8707 (curproxy->options2 & cfg_opts2[optnum].val)) {
8708 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8709 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
8710 err_code |= ERR_WARN;
8711 curproxy->options2 &= ~cfg_opts2[optnum].val;
8712 }
8713 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008714
Willy Tarreau29fbe512015-08-20 19:35:14 +02008715#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008716 if (curproxy->conn_src.bind_hdr_occ) {
8717 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008718 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01008719 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008720 err_code |= ERR_WARN;
8721 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008722#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008723 }
8724
Willy Tarreaubaaee002006-06-26 02:48:02 +02008725 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01008726 * ensure that we're not cross-dressing a TCP server into HTTP.
8727 */
8728 newsrv = curproxy->srv;
8729 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01008730 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008731 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
8732 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008733 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01008734 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008735
Willy Tarreau0cec3312011-10-31 13:49:26 +01008736 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
8737 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
8738 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8739 err_code |= ERR_WARN;
8740 }
8741
Willy Tarreauc93cd162014-05-13 15:54:22 +02008742 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02008743 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
8744 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8745 err_code |= ERR_WARN;
8746 }
8747
Willy Tarreau29fbe512015-08-20 19:35:14 +02008748#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008749 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
8750 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008751 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01008752 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008753 err_code |= ERR_WARN;
8754 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008755#endif
Willy Tarreau4c183462017-01-06 12:21:38 +01008756
8757 if ((curproxy->options & PR_O_REUSE_MASK) != PR_O_REUSE_NEVR) {
8758 if ((curproxy->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CLI ||
8759 (curproxy->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CIP ||
8760 (newsrv->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CLI ||
8761 (newsrv->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CIP) {
8762 Warning("config : %s '%s' : connections to server '%s' use the client's IP address as the source while http-reuse is enabled and allows the same connection to be shared between multiple clients. It is strongly advised to disable 'usesrc' and to use the 'forwardfor' option instead.\n",
8763 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8764 err_code |= ERR_WARN;
8765 }
8766
8767
8768 if (newsrv->pp_opts & (SRV_PP_V1|SRV_PP_V2)) {
8769 Warning("config : %s '%s' : connections to server '%s' will have a PROXY protocol header announcing the first client's IP address while http-reuse is enabled and allows the same connection to be shared between multiple clients. It is strongly advised to disable 'send-proxy' and to use the 'forwardfor' option instead.\n",
8770 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8771 err_code |= ERR_WARN;
8772 }
8773 }
8774
Willy Tarreau21d2af32008-02-14 20:25:24 +01008775 newsrv = newsrv->next;
8776 }
8777
Willy Tarreaue42bd962014-09-16 16:21:19 +02008778 /* check if we have a frontend with "tcp-request content" looking at L7
8779 * with no inspect-delay
8780 */
8781 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
8782 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008783 if (trule->action == ACT_TCP_CAPTURE &&
Thierry FOURNIERd0d65ae2015-08-04 08:21:12 +02008784 !(trule->arg.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008785 break;
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008786 if ((trule->action >= ACT_ACTION_TRK_SC0 && trule->action <= ACT_ACTION_TRK_SCMAX) &&
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008787 !(trule->arg.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008788 break;
8789 }
8790
8791 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
8792 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
8793 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
8794 " This means that these rules will randomly find their contents. This can be fixed by"
8795 " setting the tcp-request inspect-delay.\n",
8796 proxy_type_str(curproxy), curproxy->id);
8797 err_code |= ERR_WARN;
8798 }
8799 }
8800
Christopher Fauletd7c91962015-04-30 11:48:27 +02008801 /* Check filter configuration, if any */
8802 cfgerr += flt_check(curproxy);
8803
Willy Tarreauc1a21672009-08-16 22:37:44 +02008804 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02008805 if (!curproxy->accept)
8806 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02008807
Willy Tarreauc1a21672009-08-16 22:37:44 +02008808 if (curproxy->tcp_req.inspect_delay ||
8809 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02008810 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008811
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008812 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008813 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008814 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008815 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008816
8817 /* both TCP and HTTP must check switching rules */
8818 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008819
8820 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008821 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008822 curproxy->fe_req_ana |= AN_REQ_FLT_START_FE | AN_REQ_FLT_XFER_DATA | AN_REQ_FLT_END;
8823 curproxy->fe_rsp_ana |= AN_RES_FLT_START_FE | AN_RES_FLT_XFER_DATA | AN_RES_FLT_END;
Christopher Faulet309c6412015-12-02 09:57:32 +01008824 if (curproxy->mode == PR_MODE_HTTP) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008825 curproxy->fe_req_ana |= AN_REQ_FLT_HTTP_HDRS;
8826 curproxy->fe_rsp_ana |= AN_RES_FLT_HTTP_HDRS;
Christopher Faulet309c6412015-12-02 09:57:32 +01008827 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008828 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008829 }
8830
8831 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02008832 if (curproxy->tcp_req.inspect_delay ||
8833 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
8834 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
8835
Emeric Brun97679e72010-09-23 17:56:44 +02008836 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
8837 curproxy->be_rsp_ana |= AN_RES_INSPECT;
8838
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008839 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008840 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008841 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008842 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008843
8844 /* If the backend does requires RDP cookie persistence, we have to
8845 * enable the corresponding analyser.
8846 */
8847 if (curproxy->options2 & PR_O2_RDPC_PRST)
8848 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008849
8850 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008851 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008852 curproxy->be_req_ana |= AN_REQ_FLT_START_BE | AN_REQ_FLT_XFER_DATA | AN_REQ_FLT_END;
8853 curproxy->be_rsp_ana |= AN_RES_FLT_START_BE | AN_RES_FLT_XFER_DATA | AN_RES_FLT_END;
Christopher Faulet309c6412015-12-02 09:57:32 +01008854 if (curproxy->mode == PR_MODE_HTTP) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008855 curproxy->be_req_ana |= AN_REQ_FLT_HTTP_HDRS;
8856 curproxy->be_rsp_ana |= AN_RES_FLT_HTTP_HDRS;
Christopher Faulet309c6412015-12-02 09:57:32 +01008857 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008858 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008859 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008860 }
8861
8862 /***********************************************************/
8863 /* At this point, target names have already been resolved. */
8864 /***********************************************************/
8865
8866 /* Check multi-process mode compatibility */
8867
8868 if (global.nbproc > 1 && global.stats_fe) {
8869 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8870 unsigned long mask;
8871
8872 mask = nbits(global.nbproc);
8873 if (global.stats_fe->bind_proc)
8874 mask &= global.stats_fe->bind_proc;
8875
8876 if (bind_conf->bind_proc)
8877 mask &= bind_conf->bind_proc;
8878
8879 /* stop here if more than one process is used */
David Carliere6c39412015-07-02 07:00:17 +00008880 if (my_popcountl(mask) > 1)
Willy Tarreau419ead82014-09-16 13:41:21 +02008881 break;
8882 }
8883 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
8884 Warning("stats socket will not work as expected in multi-process mode (nbproc > 1), you should force process binding globally using 'stats bind-process' or per socket using the 'process' attribute.\n");
8885 }
8886 }
8887
8888 /* Make each frontend inherit bind-process from its listeners when not specified. */
8889 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8890 if (curproxy->bind_proc)
8891 continue;
8892
8893 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8894 unsigned long mask;
8895
Willy Tarreaue428b082015-05-04 21:57:58 +02008896 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008897 curproxy->bind_proc |= mask;
8898 }
8899
8900 if (!curproxy->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008901 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008902 }
8903
8904 if (global.stats_fe) {
8905 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8906 unsigned long mask;
8907
Cyril Bonté06181952016-02-24 00:14:54 +01008908 mask = bind_conf->bind_proc ? bind_conf->bind_proc : 0;
Willy Tarreau419ead82014-09-16 13:41:21 +02008909 global.stats_fe->bind_proc |= mask;
8910 }
8911 if (!global.stats_fe->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008912 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008913 }
8914
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02008915 /* propagate bindings from frontends to backends. Don't do it if there
8916 * are any fatal errors as we must not call it with unresolved proxies.
8917 */
8918 if (!cfgerr) {
8919 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8920 if (curproxy->cap & PR_CAP_FE)
8921 propagate_processes(curproxy, NULL);
8922 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008923 }
8924
8925 /* Bind each unbound backend to all processes when not specified. */
8926 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8927 if (curproxy->bind_proc)
8928 continue;
Willy Tarreaue428b082015-05-04 21:57:58 +02008929 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008930 }
8931
8932 /*******************************************************/
8933 /* At this step, all proxies have a non-null bind_proc */
8934 /*******************************************************/
8935
8936 /* perform the final checks before creating tasks */
8937
8938 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8939 struct listener *listener;
8940 unsigned int next_id;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008941
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008942 /* Configure SSL for each bind line.
8943 * Note: if configuration fails at some point, the ->ctx member
8944 * remains NULL so that listeners can later detach.
8945 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008946 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Willy Tarreau55d37912016-12-21 23:38:39 +01008947 if (bind_conf->xprt->prepare_bind_conf &&
8948 bind_conf->xprt->prepare_bind_conf(bind_conf) < 0)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008949 cfgerr++;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008950 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008951
Willy Tarreaue6b98942007-10-29 01:09:36 +01008952 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008953 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008954 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008955 int nbproc;
8956
8957 nbproc = my_popcountl(curproxy->bind_proc &
Cyril Bonté4920d702016-04-15 07:58:43 +02008958 (listener->bind_conf->bind_proc ? listener->bind_conf->bind_proc : curproxy->bind_proc) &
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008959 nbits(global.nbproc));
8960
8961 if (!nbproc) /* no intersection between listener and frontend */
8962 nbproc = 1;
8963
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008964 if (!listener->luid) {
8965 /* listener ID not set, use automatic numbering with first
8966 * spare entry starting with next_luid.
8967 */
8968 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
8969 listener->conf.id.key = listener->luid = next_id;
8970 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008971 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01008972 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008973
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008974 /* enable separate counters */
8975 if (curproxy->options2 & PR_O2_SOCKSTAT) {
Willy Tarreauae9bea02016-11-25 14:44:52 +01008976 listener->counters = calloc(1, sizeof(*listener->counters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01008977 if (!listener->name)
8978 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008979 }
Willy Tarreau81796be2012-09-22 19:11:47 +02008980
Willy Tarreaue6b98942007-10-29 01:09:36 +01008981 if (curproxy->options & PR_O_TCP_NOLING)
8982 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02008983 if (!listener->maxconn)
8984 listener->maxconn = curproxy->maxconn;
8985 if (!listener->backlog)
8986 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01008987 if (!listener->maxaccept)
8988 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
8989
8990 /* we want to have an optimal behaviour on single process mode to
8991 * maximize the work at once, but in multi-process we want to keep
8992 * some fairness between processes, so we target half of the max
8993 * number of events to be balanced over all the processes the proxy
8994 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
8995 * used to disable the limit.
8996 */
8997 if (listener->maxaccept > 0) {
8998 if (nbproc > 1)
8999 listener->maxaccept = (listener->maxaccept + 1) / 2;
9000 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
9001 }
9002
Willy Tarreau9903f0e2015-04-04 18:50:31 +02009003 listener->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02009004 listener->handler = process_stream;
Willy Tarreauc1a21672009-08-16 22:37:44 +02009005 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01009006 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01009007
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02009008 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
Willy Tarreau7d9736f2016-10-21 16:34:21 +02009009 listener->options |= LI_O_TCP_L4_RULES;
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02009010
Willy Tarreau620408f2016-10-21 16:37:51 +02009011 if (!LIST_ISEMPTY(&curproxy->tcp_req.l5_rules))
9012 listener->options |= LI_O_TCP_L5_RULES;
9013
Willy Tarreaude3041d2010-05-31 10:56:17 +02009014 if (curproxy->mon_mask.s_addr)
9015 listener->options |= LI_O_CHK_MONNET;
9016
Willy Tarreau9ea05a72009-06-14 12:07:01 +02009017 /* smart accept mode is automatic in HTTP mode */
9018 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02009019 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02009020 !(curproxy->no_options2 & PR_O2_SMARTACC)))
9021 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01009022 }
9023
Willy Tarreau2a65ff02012-09-13 17:54:29 +02009024 /* Release unused SSL configs */
9025 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Willy Tarreau795cdab2016-12-22 17:30:54 +01009026 if (!bind_conf->is_ssl && bind_conf->xprt->destroy_bind_conf)
9027 bind_conf->xprt->destroy_bind_conf(bind_conf);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02009028 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02009029
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02009030 if (my_popcountl(curproxy->bind_proc & nbits(global.nbproc)) > 1) {
Willy Tarreau102df612014-05-07 23:56:38 +02009031 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02009032 int count, maxproc = 0;
9033
9034 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
David Carliere6c39412015-07-02 07:00:17 +00009035 count = my_popcountl(bind_conf->bind_proc);
Willy Tarreaueb791e02014-09-16 15:11:04 +02009036 if (count > maxproc)
9037 maxproc = count;
9038 }
9039 /* backends have 0, frontends have 1 or more */
9040 if (maxproc != 1)
9041 Warning("Proxy '%s': in multi-process mode, stats will be"
9042 " limited to process assigned to the current request.\n",
9043 curproxy->id);
9044
Willy Tarreau102df612014-05-07 23:56:38 +02009045 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
9046 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
9047 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01009048 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01009049 }
Willy Tarreau102df612014-05-07 23:56:38 +02009050 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
9051 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
9052 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01009053 }
9054 }
Willy Tarreau918ff602011-07-25 16:33:49 +02009055
9056 /* create the task associated with the proxy */
9057 curproxy->task = task_new();
9058 if (curproxy->task) {
9059 curproxy->task->context = curproxy;
9060 curproxy->task->process = manage_proxy;
9061 /* no need to queue, it will be done automatically if some
9062 * listener gets limited.
9063 */
9064 curproxy->task->expire = TICK_ETERNITY;
9065 } else {
9066 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
9067 curproxy->id);
9068 cfgerr++;
9069 }
Willy Tarreaub369a042014-09-16 13:21:03 +02009070 }
9071
Willy Tarreaufbb78422011-06-05 15:38:35 +02009072 /* automatically compute fullconn if not set. We must not do it in the
9073 * loop above because cross-references are not yet fully resolved.
9074 */
9075 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9076 /* If <fullconn> is not set, let's set it to 10% of the sum of
9077 * the possible incoming frontend's maxconns.
9078 */
9079 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02009080 /* we have the sum of the maxconns in <total>. We only
9081 * keep 10% of that sum to set the default fullconn, with
9082 * a hard minimum of 1 (to avoid a divide by zero).
9083 */
Emeric Brun3f783572017-01-12 11:21:28 +01009084 curproxy->fullconn = (curproxy->tot_fe_maxconn + 9) / 10;
Willy Tarreaufbb78422011-06-05 15:38:35 +02009085 if (!curproxy->fullconn)
9086 curproxy->fullconn = 1;
9087 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01009088 }
9089
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009090 /*
9091 * Recount currently required checks.
9092 */
9093
9094 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
9095 int optnum;
9096
Willy Tarreau66aa61f2009-01-18 21:44:07 +01009097 for (optnum = 0; cfg_opts[optnum].name; optnum++)
9098 if (curproxy->options & cfg_opts[optnum].val)
9099 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009100
Willy Tarreau66aa61f2009-01-18 21:44:07 +01009101 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
9102 if (curproxy->options2 & cfg_opts2[optnum].val)
9103 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009104 }
9105
Willy Tarreau0fca4832015-05-01 19:12:05 +02009106 /* compute the required process bindings for the peers */
9107 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
9108 if (curproxy->table.peers.p)
9109 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
9110
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02009111 if (cfg_peers) {
9112 struct peers *curpeers = cfg_peers, **last;
Willy Tarreau122541c2011-09-07 21:24:49 +02009113 struct peer *p, *pb;
9114
Willy Tarreau1e273012015-05-01 19:15:17 +02009115 /* Remove all peers sections which don't have a valid listener,
9116 * which are not used by any table, or which are bound to more
9117 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02009118 */
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02009119 last = &cfg_peers;
Willy Tarreau122541c2011-09-07 21:24:49 +02009120 while (*last) {
9121 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009122
9123 if (curpeers->state == PR_STSTOPPED) {
9124 /* the "disabled" keyword was present */
9125 if (curpeers->peers_fe)
9126 stop_proxy(curpeers->peers_fe);
9127 curpeers->peers_fe = NULL;
9128 }
9129 else if (!curpeers->peers_fe) {
9130 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
9131 curpeers->id, localpeer);
9132 }
David Carliere6c39412015-07-02 07:00:17 +00009133 else if (my_popcountl(curpeers->peers_fe->bind_proc) != 1) {
Willy Tarreau1e273012015-05-01 19:15:17 +02009134 /* either it's totally stopped or too much used */
9135 if (curpeers->peers_fe->bind_proc) {
9136 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreau64c57222015-05-04 21:48:51 +02009137 "running in different processes (%d different ones). "
9138 "Check global.nbproc and all tables' bind-process "
David Carliere6c39412015-07-02 07:00:17 +00009139 "settings.\n", curpeers->id, my_popcountl(curpeers->peers_fe->bind_proc));
Willy Tarreau1e273012015-05-01 19:15:17 +02009140 cfgerr++;
9141 }
9142 stop_proxy(curpeers->peers_fe);
9143 curpeers->peers_fe = NULL;
9144 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009145 else {
Emeric Brunb3971ab2015-05-12 18:49:09 +02009146 peers_init_sync(curpeers);
Willy Tarreau122541c2011-09-07 21:24:49 +02009147 last = &curpeers->next;
9148 continue;
9149 }
9150
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009151 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02009152 p = curpeers->remote;
9153 while (p) {
9154 pb = p->next;
9155 free(p->id);
9156 free(p);
9157 p = pb;
9158 }
9159
9160 /* Destroy and unlink this curpeers section.
9161 * Note: curpeers is backed up into *last.
9162 */
9163 free(curpeers->id);
9164 curpeers = curpeers->next;
9165 free(*last);
9166 *last = curpeers;
9167 }
9168 }
9169
Willy Tarreau6866f3f2015-05-01 19:09:08 +02009170 /* initialize stick-tables on backend capable proxies. This must not
9171 * be done earlier because the data size may be discovered while parsing
9172 * other proxies.
9173 */
9174 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9175 if (curproxy->state == PR_STSTOPPED)
9176 continue;
9177
9178 if (!stktable_init(&curproxy->table)) {
9179 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
9180 cfgerr++;
9181 }
9182 }
9183
Simon Horman0d16a402015-01-30 11:22:58 +09009184 if (mailers) {
9185 struct mailers *curmailers = mailers, **last;
9186 struct mailer *m, *mb;
9187
9188 /* Remove all mailers sections which don't have a valid listener.
9189 * This can happen when a mailers section is never referenced.
9190 */
9191 last = &mailers;
9192 while (*last) {
9193 curmailers = *last;
9194 if (curmailers->users) {
9195 last = &curmailers->next;
9196 continue;
9197 }
9198
9199 Warning("Removing incomplete section 'mailers %s'.\n",
9200 curmailers->id);
9201
9202 m = curmailers->mailer_list;
9203 while (m) {
9204 mb = m->next;
9205 free(m->id);
9206 free(m);
9207 m = mb;
9208 }
9209
9210 /* Destroy and unlink this curmailers section.
9211 * Note: curmailers is backed up into *last.
9212 */
9213 free(curmailers->id);
9214 curmailers = curmailers->next;
9215 free(*last);
9216 *last = curmailers;
9217 }
9218 }
9219
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02009220 /* Update server_state_file_name to backend name if backend is supposed to use
9221 * a server-state file locally defined and none has been provided */
9222 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9223 if (curproxy->load_server_state_from_file == PR_SRV_STATE_FILE_LOCAL &&
9224 curproxy->server_state_file_name == NULL)
9225 curproxy->server_state_file_name = strdup(curproxy->id);
9226 }
9227
Willy Tarreau34eb6712011-10-24 18:15:04 +02009228 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02009229 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02009230 MEM_F_SHARED);
9231
Willy Tarreaubb925012009-07-23 13:36:36 +02009232 if (cfgerr > 0)
9233 err_code |= ERR_ALERT | ERR_FATAL;
9234 out:
9235 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02009236}
9237
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009238/*
9239 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
9240 * parsing sessions.
9241 */
9242void cfg_register_keywords(struct cfg_kw_list *kwl)
9243{
9244 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
9245}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009246
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009247/*
9248 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
9249 */
9250void cfg_unregister_keywords(struct cfg_kw_list *kwl)
9251{
9252 LIST_DEL(&kwl->list);
9253 LIST_INIT(&kwl->list);
9254}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009255
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009256/* this function register new section in the haproxy configuration file.
9257 * <section_name> is the name of this new section and <section_parser>
9258 * is the called parser. If two section declaration have the same name,
9259 * only the first declared is used.
9260 */
9261int cfg_register_section(char *section_name,
9262 int (*section_parser)(const char *, int, char **, int))
9263{
9264 struct cfg_section *cs;
9265
Willy Tarreau5e4261b2016-05-17 16:16:09 +02009266 list_for_each_entry(cs, &sections, list) {
9267 if (strcmp(cs->section_name, section_name) == 0) {
9268 Alert("register section '%s': already registered.\n", section_name);
9269 return 0;
9270 }
9271 }
9272
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009273 cs = calloc(1, sizeof(*cs));
9274 if (!cs) {
9275 Alert("register section '%s': out of memory.\n", section_name);
9276 return 0;
9277 }
9278
9279 cs->section_name = section_name;
9280 cs->section_parser = section_parser;
9281
9282 LIST_ADDQ(&sections, &cs->list);
9283
9284 return 1;
9285}
9286
Willy Tarreaubaaee002006-06-26 02:48:02 +02009287/*
David Carlier845efb52015-09-25 11:49:18 +01009288 * free all config section entries
9289 */
9290void cfg_unregister_sections(void)
9291{
9292 struct cfg_section *cs, *ics;
9293
9294 list_for_each_entry_safe(cs, ics, &sections, list) {
9295 LIST_DEL(&cs->list);
9296 free(cs);
9297 }
9298}
9299
Christopher Faulet7110b402016-10-26 11:09:44 +02009300void cfg_backup_sections(struct list *backup_sections)
9301{
9302 struct cfg_section *cs, *ics;
9303
9304 list_for_each_entry_safe(cs, ics, &sections, list) {
9305 LIST_DEL(&cs->list);
9306 LIST_ADDQ(backup_sections, &cs->list);
9307 }
9308}
9309
9310void cfg_restore_sections(struct list *backup_sections)
9311{
9312 struct cfg_section *cs, *ics;
9313
9314 list_for_each_entry_safe(cs, ics, backup_sections, list) {
9315 LIST_DEL(&cs->list);
9316 LIST_ADDQ(&sections, &cs->list);
9317 }
9318}
9319
Willy Tarreau659fbf02016-05-26 17:55:28 +02009320__attribute__((constructor))
9321static void cfgparse_init(void)
9322{
9323 /* Register internal sections */
9324 cfg_register_section("listen", cfg_parse_listen);
9325 cfg_register_section("frontend", cfg_parse_listen);
9326 cfg_register_section("backend", cfg_parse_listen);
9327 cfg_register_section("defaults", cfg_parse_listen);
9328 cfg_register_section("global", cfg_parse_global);
9329 cfg_register_section("userlist", cfg_parse_users);
9330 cfg_register_section("peers", cfg_parse_peers);
9331 cfg_register_section("mailers", cfg_parse_mailers);
9332 cfg_register_section("namespace_list", cfg_parse_netns);
9333 cfg_register_section("resolvers", cfg_parse_resolvers);
9334}
9335
David Carlier845efb52015-09-25 11:49:18 +01009336/*
Willy Tarreaubaaee002006-06-26 02:48:02 +02009337 * Local variables:
9338 * c-indent-level: 8
9339 * c-basic-offset: 8
9340 * End:
9341 */