blob: d732ac3286144e4c7a36e9cd94fb6f011a964afe [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>
Willy Tarreaubaaee002006-06-26 02:48:02 +020048#include <types/global.h>
Willy Tarreau3fdb3662012-11-12 00:42:33 +010049#include <types/obj_type.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020050#include <types/peers.h>
Simon Horman0d16a402015-01-30 11:22:58 +090051#include <types/mailers.h>
Baptiste Assmann325137d2015-04-13 23:40:55 +020052#include <types/dns.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020053
Willy Tarreaueb0c6142007-05-07 00:53:22 +020054#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010055#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020056#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020057#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020058#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020059#include <proto/compression.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020060#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020061#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020062#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020063#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010064#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020065#include <proto/lb_fwlc.h>
66#include <proto/lb_fwrr.h>
67#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020068#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020069#include <proto/log.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020070#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010071#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020072#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010073#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010074#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020075#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020076#include <proto/sample.h>
Willy Tarreau9903f0e2015-04-04 18:50:31 +020077#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020078#include <proto/server.h>
Willy Tarreau87b09662015-04-03 00:22:06 +020079#include <proto/stream.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020080#include <proto/raw_sock.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020081#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010082#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020083
Emeric Brunfc0421f2012-09-07 17:30:07 +020084#ifdef USE_OPENSSL
85#include <types/ssl_sock.h>
86#include <proto/ssl_sock.h>
87#include <proto/shctx.h>
88#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020089
Willy Tarreauf3c69202006-07-09 16:42:34 +020090/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
91 * ssl-hello-chk option to ensure that the remote server speaks SSL.
92 *
93 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
94 */
95const char sslv3_client_hello_pkt[] = {
96 "\x16" /* ContentType : 0x16 = Hanshake */
97 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
98 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
99 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
100 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
101 "\x03\x00" /* Hello Version : 0x0300 = v3 */
102 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
103 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
104 "\x00" /* Session ID length : empty (no session ID) */
105 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
106 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
107 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
108 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
109 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
110 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
111 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
112 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
113 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
114 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
115 "\x00\x38" "\x00\x39" "\x00\x3A"
116 "\x01" /* Compression Length : 0x01 = 1 byte for types */
117 "\x00" /* Compression Type : 0x00 = NULL compression */
118};
119
Willy Tarreau3842f002009-06-14 11:39:52 +0200120/* various keyword modifiers */
121enum kw_mod {
122 KWM_STD = 0, /* normal */
123 KWM_NO, /* "no" prefixed before the keyword */
124 KWM_DEF, /* "default" prefixed before the keyword */
125};
126
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +0100127/* permit to store configuration section */
128struct cfg_section {
129 struct list list;
130 char *section_name;
131 int (*section_parser)(const char *, int, char **, int);
132};
133
134/* Used to chain configuration sections definitions. This list
135 * stores struct cfg_section
136 */
137struct list sections = LIST_HEAD_INIT(sections);
138
Willy Tarreau13943ab2006-12-31 00:24:10 +0100139/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100140struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100141 const char *name;
142 unsigned int val;
143 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100144 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100145 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100146};
147
148/* proxy->options */
149static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100150{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100151 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
152 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
153 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
154 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
155 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
156 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100157 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau9fbe18e2015-05-01 22:42:08 +0200158 { "http-buffer-request", PR_O_WREQ_BODY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau0f228a02015-05-01 15:37:53 +0200159 { "http-ignore-probes", PR_O_IGNORE_PRB, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreau9420b122013-12-15 18:58:25 +0100160 { "prefer-last-server", PR_O_PREF_LAST, PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100161 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
162 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
163 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100164 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100165#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100166 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100167#else
168 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100169#endif
170
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100171 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100172};
173
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100174/* proxy->options2 */
175static const struct cfg_opt cfg_opts2[] =
176{
177#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100178 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
179 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
180 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100181#else
182 { "splice-request", 0, 0, 0, 0 },
183 { "splice-response", 0, 0, 0, 0 },
184 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100185#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100186 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
187 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
188 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
189 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
190 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
191 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
192 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
193 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
194 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400195 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100196 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200197 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200198 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100199 { NULL, 0, 0, 0 }
200};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200201
Willy Tarreau6daf3432008-01-22 16:44:08 +0100202static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200203static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
204int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100205int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
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 Tarreau12eb2a62013-03-06 15:45:03 +0100241 ss2 = str2sa_range(str, &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 */
288 ss = *ss2;
289
Willy Tarreaubaaee002006-06-26 02:48:02 +0200290 for (; port <= end; port++) {
291 l = (struct listener *)calloc(1, sizeof(struct listener));
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);
295 l->frontend = curproxy;
296 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200297
Willy Tarreau40aa0702013-03-10 23:51:38 +0100298 l->fd = fd;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200299 l->addr = ss;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200300 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100301 l->state = LI_INIT;
302
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100303 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200304 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100305 tcpv4_add_listener(l);
306 }
Emeric Bruned760922010-10-22 17:59:25 +0200307 else if (ss.ss_family == AF_INET6) {
308 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
309 tcpv6_add_listener(l);
310 }
311 else {
Emeric Bruned760922010-10-22 17:59:25 +0200312 uxst_add_listener(l);
313 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200314
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200315 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100316 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200317 } /* end for(port) */
318 } /* end while(next) */
319 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200320 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200321 fail:
322 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200323 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200324}
325
William Lallemand6e62fb62015-04-28 16:55:23 +0200326/*
327 * Report a fatal Alert when there is too much arguments
328 * The index is the current keyword in args
329 * Return 0 if the number of argument is correct, otherwise emit an alert and return 1
330 * Fill err_code with an ERR_ALERT and an ERR_FATAL
331 */
332int alertif_too_many_args_idx(int maxarg, int index, const char *file, int linenum, char **args, int *err_code)
333{
334 char *kw = NULL;
335 int i;
336
337 if (!*args[index + maxarg + 1])
338 return 0;
339
340 memprintf(&kw, "%s", args[0]);
341 for (i = 1; i <= index; i++) {
342 memprintf(&kw, "%s %s", kw, args[i]);
343 }
344
345 Alert("parsing [%s:%d] : '%s' cannot handle unexpected argument '%s'.\n", file, linenum, kw, args[index + maxarg + 1]);
346 free(kw);
347 *err_code |= ERR_ALERT | ERR_FATAL;
348 return 1;
349}
350
351/*
352 * same as alertif_too_many_args_idx with a 0 index
353 */
354int alertif_too_many_args(int maxarg, const char *file, int linenum, char **args, int *err_code)
355{
356 return alertif_too_many_args_idx(maxarg, 0, file, linenum, args, err_code);
357}
358
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200359/* Report a warning if a rule is placed after a 'tcp-request content' rule.
360 * Return 1 if the warning has been emitted, otherwise 0.
361 */
362int warnif_rule_after_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
363{
364 if (!LIST_ISEMPTY(&proxy->tcp_req.inspect_rules)) {
365 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request content' rule will still be processed before.\n",
366 file, line, arg);
367 return 1;
368 }
369 return 0;
370}
371
Willy Tarreau61d18892009-03-31 10:49:21 +0200372/* Report a warning if a rule is placed after a 'block' rule.
373 * Return 1 if the warning has been emitted, otherwise 0.
374 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100375int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200376{
Willy Tarreau353bc9f2014-04-28 22:05:31 +0200377 if (!LIST_ISEMPTY(&proxy->block_rules)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200378 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
379 file, line, arg);
380 return 1;
381 }
382 return 0;
383}
384
Willy Tarreau5002f572014-04-23 01:32:02 +0200385/* Report a warning if a rule is placed after an 'http_request' rule.
386 * Return 1 if the warning has been emitted, otherwise 0.
387 */
388int warnif_rule_after_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
389{
390 if (!LIST_ISEMPTY(&proxy->http_req_rules)) {
391 Warning("parsing [%s:%d] : a '%s' rule placed after an 'http-request' rule will still be processed before.\n",
392 file, line, arg);
393 return 1;
394 }
395 return 0;
396}
397
Willy Tarreau61d18892009-03-31 10:49:21 +0200398/* Report a warning if a rule is placed after a reqrewrite rule.
399 * Return 1 if the warning has been emitted, otherwise 0.
400 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100401int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200402{
403 if (proxy->req_exp) {
404 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
405 file, line, arg);
406 return 1;
407 }
408 return 0;
409}
410
411/* Report a warning if a rule is placed after a reqadd rule.
412 * Return 1 if the warning has been emitted, otherwise 0.
413 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100414int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200415{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100416 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200417 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
418 file, line, arg);
419 return 1;
420 }
421 return 0;
422}
423
424/* Report a warning if a rule is placed after a redirect rule.
425 * Return 1 if the warning has been emitted, otherwise 0.
426 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100427int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200428{
429 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
430 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
431 file, line, arg);
432 return 1;
433 }
434 return 0;
435}
436
437/* Report a warning if a rule is placed after a 'use_backend' rule.
438 * Return 1 if the warning has been emitted, otherwise 0.
439 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100440int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200441{
442 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
443 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
444 file, line, arg);
445 return 1;
446 }
447 return 0;
448}
449
Willy Tarreauee445d92014-04-23 01:39:04 +0200450/* Report a warning if a rule is placed after a 'use-server' rule.
451 * Return 1 if the warning has been emitted, otherwise 0.
452 */
453int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line, const char *arg)
454{
455 if (!LIST_ISEMPTY(&proxy->server_rules)) {
456 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use-server' rule will still be processed before.\n",
457 file, line, arg);
458 return 1;
459 }
460 return 0;
461}
462
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200463/* report a warning if a "tcp request connection" rule is dangerously placed */
464int warnif_misplaced_tcp_conn(struct proxy *proxy, const char *file, int line, const char *arg)
465{
466 return warnif_rule_after_tcp_cont(proxy, file, line, arg) ||
467 warnif_rule_after_block(proxy, file, line, arg) ||
468 warnif_rule_after_http_req(proxy, file, line, arg) ||
469 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
470 warnif_rule_after_reqadd(proxy, file, line, arg) ||
471 warnif_rule_after_redirect(proxy, file, line, arg) ||
472 warnif_rule_after_use_backend(proxy, file, line, arg) ||
473 warnif_rule_after_use_server(proxy, file, line, arg);
474}
475
476/* report a warning if a "tcp request content" rule is dangerously placed */
477int warnif_misplaced_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
478{
479 return warnif_rule_after_block(proxy, file, line, arg) ||
480 warnif_rule_after_http_req(proxy, file, line, arg) ||
481 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
482 warnif_rule_after_reqadd(proxy, file, line, arg) ||
483 warnif_rule_after_redirect(proxy, file, line, arg) ||
484 warnif_rule_after_use_backend(proxy, file, line, arg) ||
485 warnif_rule_after_use_server(proxy, file, line, arg);
486}
487
Willy Tarreau61d18892009-03-31 10:49:21 +0200488/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100489int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200490{
Willy Tarreau5002f572014-04-23 01:32:02 +0200491 return warnif_rule_after_http_req(proxy, file, line, arg) ||
492 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
493 warnif_rule_after_reqadd(proxy, file, line, arg) ||
494 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200495 warnif_rule_after_use_backend(proxy, file, line, arg) ||
496 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau5002f572014-04-23 01:32:02 +0200497}
498
499/* report a warning if an http-request rule is dangerously placed */
500int warnif_misplaced_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
501{
Willy Tarreau61d18892009-03-31 10:49:21 +0200502 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
503 warnif_rule_after_reqadd(proxy, file, line, arg) ||
504 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200505 warnif_rule_after_use_backend(proxy, file, line, arg) ||
506 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200507}
508
509/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100510int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200511{
512 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
513 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200514 warnif_rule_after_use_backend(proxy, file, line, arg) ||
515 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200516}
517
518/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100519int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200520{
521 return warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200522 warnif_rule_after_use_backend(proxy, file, line, arg) ||
523 warnif_rule_after_use_server(proxy, file, line, arg);
524}
525
526/* report a warning if a redirect rule is dangerously placed */
527int warnif_misplaced_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
528{
529 return warnif_rule_after_use_backend(proxy, file, line, arg) ||
530 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200531}
532
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100533/* Report it if a request ACL condition uses some keywords that are incompatible
534 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
535 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
536 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100537 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100538static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100539{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100540 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200541 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100542
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100543 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100544 return 0;
545
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100546 acl = acl_cond_conflicts(cond, where);
547 if (acl) {
548 if (acl->name && *acl->name)
549 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
550 file, line, acl->name, sample_ckp_names(where));
551 else
552 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 +0200553 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100554 return ERR_WARN;
555 }
556 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100557 return 0;
558
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100559 if (acl->name && *acl->name)
560 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200561 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100562 else
563 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200564 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100565 return ERR_WARN;
566}
567
Willy Tarreaubaaee002006-06-26 02:48:02 +0200568/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200569 * parse a line in a <global> section. Returns the error code, 0 if OK, or
570 * any combination of :
571 * - ERR_ABORT: must abort ASAP
572 * - ERR_FATAL: we can continue parsing but not start the service
573 * - ERR_WARN: a warning has been emitted
574 * - ERR_ALERT: an alert has been emitted
575 * Only the two first ones can stop processing, the two others are just
576 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200577 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200578int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200579{
Willy Tarreau058e9072009-07-20 09:30:05 +0200580 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200581 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200582
583 if (!strcmp(args[0], "global")) { /* new section */
584 /* no option, nothing special to do */
William Lallemand6e62fb62015-04-28 16:55:23 +0200585 alertif_too_many_args(0, file, linenum, args, &err_code);
Willy Tarreau058e9072009-07-20 09:30:05 +0200586 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200587 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200588 else if (!strcmp(args[0], "ca-base")) {
589#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +0200590 if(alertif_too_many_args(1, file, linenum, args, &err_code))
591 goto out;
Emeric Brunc8e8d122012-10-02 18:42:10 +0200592 if (global.ca_base != NULL) {
593 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
594 err_code |= ERR_ALERT;
595 goto out;
596 }
597 if (*(args[1]) == 0) {
598 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
599 err_code |= ERR_ALERT | ERR_FATAL;
600 goto out;
601 }
602 global.ca_base = strdup(args[1]);
603#else
604 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
605 err_code |= ERR_ALERT | ERR_FATAL;
606 goto out;
607#endif
608 }
609 else if (!strcmp(args[0], "crt-base")) {
610#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +0200611 if (alertif_too_many_args(1, file, linenum, args, &err_code))
612 goto out;
Emeric Brunc8e8d122012-10-02 18:42:10 +0200613 if (global.crt_base != NULL) {
614 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
615 err_code |= ERR_ALERT;
616 goto out;
617 }
618 if (*(args[1]) == 0) {
619 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
620 err_code |= ERR_ALERT | ERR_FATAL;
621 goto out;
622 }
623 global.crt_base = strdup(args[1]);
624#else
625 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
626 err_code |= ERR_ALERT | ERR_FATAL;
627 goto out;
628#endif
629 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200630 else if (!strcmp(args[0], "daemon")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200631 if (alertif_too_many_args(0, file, linenum, args, &err_code))
632 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200633 global.mode |= MODE_DAEMON;
634 }
635 else if (!strcmp(args[0], "debug")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200636 if (alertif_too_many_args(0, file, linenum, args, &err_code))
637 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200638 global.mode |= MODE_DEBUG;
639 }
640 else if (!strcmp(args[0], "noepoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200641 if (alertif_too_many_args(0, file, linenum, args, &err_code))
642 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100643 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200644 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200645 else if (!strcmp(args[0], "nokqueue")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200646 if (alertif_too_many_args(0, file, linenum, args, &err_code))
647 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100648 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200649 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200650 else if (!strcmp(args[0], "nopoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200651 if (alertif_too_many_args(0, file, linenum, args, &err_code))
652 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100653 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200654 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100655 else if (!strcmp(args[0], "nosplice")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200656 if (alertif_too_many_args(0, file, linenum, args, &err_code))
657 goto out;
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100658 global.tune.options &= ~GTUNE_USE_SPLICE;
659 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200660 else if (!strcmp(args[0], "nogetaddrinfo")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200661 if (alertif_too_many_args(0, file, linenum, args, &err_code))
662 goto out;
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200663 global.tune.options &= ~GTUNE_USE_GAI;
664 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200665 else if (!strcmp(args[0], "quiet")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200666 if (alertif_too_many_args(0, file, linenum, args, &err_code))
667 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200668 global.mode |= MODE_QUIET;
669 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200670 else if (!strcmp(args[0], "tune.maxpollevents")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200671 if (alertif_too_many_args(1, file, linenum, args, &err_code))
672 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200673 if (global.tune.maxpollevents != 0) {
674 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200675 err_code |= ERR_ALERT;
676 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200677 }
678 if (*(args[1]) == 0) {
679 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200680 err_code |= ERR_ALERT | ERR_FATAL;
681 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200682 }
683 global.tune.maxpollevents = atol(args[1]);
684 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100685 else if (!strcmp(args[0], "tune.maxaccept")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200686 if (alertif_too_many_args(1, file, linenum, args, &err_code))
687 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100688 if (global.tune.maxaccept != 0) {
689 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200690 err_code |= ERR_ALERT;
691 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100692 }
693 if (*(args[1]) == 0) {
694 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200695 err_code |= ERR_ALERT | ERR_FATAL;
696 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100697 }
698 global.tune.maxaccept = atol(args[1]);
699 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200700 else if (!strcmp(args[0], "tune.chksize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200701 if (alertif_too_many_args(1, file, linenum, args, &err_code))
702 goto out;
Willy Tarreau43961d52010-10-04 20:39:20 +0200703 if (*(args[1]) == 0) {
704 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
705 err_code |= ERR_ALERT | ERR_FATAL;
706 goto out;
707 }
708 global.tune.chksize = atol(args[1]);
709 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200710#ifdef USE_OPENSSL
Emeric Brun8dc60392014-05-09 13:52:00 +0200711 else if (!strcmp(args[0], "tune.ssl.force-private-cache")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200712 if (alertif_too_many_args(0, file, linenum, args, &err_code))
713 goto out;
Emeric Brun8dc60392014-05-09 13:52:00 +0200714 global.tune.sslprivatecache = 1;
715 }
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100716 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200717 if (alertif_too_many_args(1, file, linenum, args, &err_code))
718 goto out;
Emeric Brunfc32aca2012-09-03 12:10:29 +0200719 if (*(args[1]) == 0) {
720 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
721 err_code |= ERR_ALERT | ERR_FATAL;
722 goto out;
723 }
724 global.tune.sslcachesize = atol(args[1]);
725 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100726 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
727 unsigned int ssllifetime;
728 const char *res;
729
William Lallemand1a748ae2015-05-19 16:37:23 +0200730 if (alertif_too_many_args(1, file, linenum, args, &err_code))
731 goto out;
Emeric Brun4f65bff2012-11-16 15:11:00 +0100732 if (*(args[1]) == 0) {
733 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
734 err_code |= ERR_ALERT | ERR_FATAL;
735 goto out;
736 }
737
738 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
739 if (res) {
740 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
741 file, linenum, *res, args[0]);
742 err_code |= ERR_ALERT | ERR_FATAL;
743 goto out;
744 }
745
746 global.tune.ssllifetime = ssllifetime;
747 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100748 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200749 if (alertif_too_many_args(1, file, linenum, args, &err_code))
750 goto out;
Willy Tarreaubfd59462013-02-21 07:46:09 +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.ssl_max_record = atol(args[1]);
757 }
Remi Gacogne47783ef2015-05-29 15:53:22 +0200758#ifndef OPENSSL_NO_DH
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200759 else if (!strcmp(args[0], "tune.ssl.default-dh-param")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200760 if (alertif_too_many_args(1, file, linenum, args, &err_code))
761 goto out;
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200762 if (*(args[1]) == 0) {
763 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
764 err_code |= ERR_ALERT | ERR_FATAL;
765 goto out;
766 }
767 global.tune.ssl_default_dh_param = atol(args[1]);
768 if (global.tune.ssl_default_dh_param < 1024) {
769 Alert("parsing [%s:%d] : '%s' expects a value >= 1024.\n", file, linenum, args[0]);
770 err_code |= ERR_ALERT | ERR_FATAL;
771 goto out;
772 }
773 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200774#endif
Christopher Faulet31af49d2015-06-09 17:29:50 +0200775 else if (!strcmp(args[0], "tune.ssl.ssl-ctx-cache-size")) {
776 if (alertif_too_many_args(1, file, linenum, args, &err_code))
777 goto out;
778 if (*(args[1]) == 0) {
779 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
780 err_code |= ERR_ALERT | ERR_FATAL;
781 goto out;
782 }
783 global.tune.ssl_ctx_cache = atoi(args[1]);
784 if (global.tune.ssl_ctx_cache < 0) {
785 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
786 file, linenum, args[0]);
787 err_code |= ERR_ALERT | ERR_FATAL;
788 goto out;
789 }
790 }
Remi Gacogne47783ef2015-05-29 15:53:22 +0200791#endif
Willy Tarreau33cb0652014-12-23 22:52:37 +0100792 else if (!strcmp(args[0], "tune.buffers.limit")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200793 if (alertif_too_many_args(1, file, linenum, args, &err_code))
794 goto out;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100795 if (*(args[1]) == 0) {
796 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
797 err_code |= ERR_ALERT | ERR_FATAL;
798 goto out;
799 }
800 global.tune.buf_limit = atol(args[1]);
801 if (global.tune.buf_limit) {
802 if (global.tune.buf_limit < 3)
803 global.tune.buf_limit = 3;
804 if (global.tune.buf_limit <= global.tune.reserved_bufs)
805 global.tune.buf_limit = global.tune.reserved_bufs + 1;
806 }
807 }
Willy Tarreau1058ae72014-12-23 22:40:40 +0100808 else if (!strcmp(args[0], "tune.buffers.reserve")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200809 if (alertif_too_many_args(1, file, linenum, args, &err_code))
810 goto out;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100811 if (*(args[1]) == 0) {
812 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
813 err_code |= ERR_ALERT | ERR_FATAL;
814 goto out;
815 }
816 global.tune.reserved_bufs = atol(args[1]);
817 if (global.tune.reserved_bufs < 2)
818 global.tune.reserved_bufs = 2;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100819 if (global.tune.buf_limit && global.tune.buf_limit <= global.tune.reserved_bufs)
820 global.tune.buf_limit = global.tune.reserved_bufs + 1;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100821 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200822 else if (!strcmp(args[0], "tune.bufsize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200823 if (alertif_too_many_args(1, file, linenum, args, &err_code))
824 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200825 if (*(args[1]) == 0) {
826 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
827 err_code |= ERR_ALERT | ERR_FATAL;
828 goto out;
829 }
830 global.tune.bufsize = atol(args[1]);
Willy Tarreau9b694542015-09-28 13:49:53 +0200831 if (global.tune.bufsize <= 0) {
832 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
833 err_code |= ERR_ALERT | ERR_FATAL;
834 goto out;
835 }
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100836 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100837 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200838 }
839 else if (!strcmp(args[0], "tune.maxrewrite")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200840 if (alertif_too_many_args(1, file, linenum, args, &err_code))
841 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200842 if (*(args[1]) == 0) {
843 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
844 err_code |= ERR_ALERT | ERR_FATAL;
845 goto out;
846 }
847 global.tune.maxrewrite = atol(args[1]);
Willy Tarreau27097842015-09-28 13:53:23 +0200848 if (global.tune.maxrewrite < 0) {
849 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
850 err_code |= ERR_ALERT | ERR_FATAL;
851 goto out;
852 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200853 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100854 else if (!strcmp(args[0], "tune.idletimer")) {
855 unsigned int idle;
856 const char *res;
857
William Lallemand1a748ae2015-05-19 16:37:23 +0200858 if (alertif_too_many_args(1, file, linenum, args, &err_code))
859 goto out;
Willy Tarreau7e312732014-02-12 16:35:14 +0100860 if (*(args[1]) == 0) {
861 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
862 err_code |= ERR_ALERT | ERR_FATAL;
863 goto out;
864 }
865
866 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
867 if (res) {
868 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
869 file, linenum, *res, args[0]);
870 err_code |= ERR_ALERT | ERR_FATAL;
871 goto out;
872 }
873
874 if (idle > 65535) {
875 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
876 err_code |= ERR_ALERT | ERR_FATAL;
877 goto out;
878 }
879 global.tune.idle_timer = idle;
880 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100881 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200882 if (alertif_too_many_args(1, file, linenum, args, &err_code))
883 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100884 if (global.tune.client_rcvbuf != 0) {
885 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
886 err_code |= ERR_ALERT;
887 goto out;
888 }
889 if (*(args[1]) == 0) {
890 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
891 err_code |= ERR_ALERT | ERR_FATAL;
892 goto out;
893 }
894 global.tune.client_rcvbuf = atol(args[1]);
895 }
896 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200897 if (alertif_too_many_args(1, file, linenum, args, &err_code))
898 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100899 if (global.tune.server_rcvbuf != 0) {
900 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
901 err_code |= ERR_ALERT;
902 goto out;
903 }
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.server_rcvbuf = atol(args[1]);
910 }
911 else if (!strcmp(args[0], "tune.sndbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200912 if (alertif_too_many_args(1, file, linenum, args, &err_code))
913 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100914 if (global.tune.client_sndbuf != 0) {
915 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
916 err_code |= ERR_ALERT;
917 goto out;
918 }
919 if (*(args[1]) == 0) {
920 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
921 err_code |= ERR_ALERT | ERR_FATAL;
922 goto out;
923 }
924 global.tune.client_sndbuf = atol(args[1]);
925 }
926 else if (!strcmp(args[0], "tune.sndbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200927 if (alertif_too_many_args(1, file, linenum, args, &err_code))
928 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100929 if (global.tune.server_sndbuf != 0) {
930 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
931 err_code |= ERR_ALERT;
932 goto out;
933 }
934 if (*(args[1]) == 0) {
935 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
936 err_code |= ERR_ALERT | ERR_FATAL;
937 goto out;
938 }
939 global.tune.server_sndbuf = atol(args[1]);
940 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200941 else if (!strcmp(args[0], "tune.pipesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200942 if (alertif_too_many_args(1, file, linenum, args, &err_code))
943 goto out;
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200944 if (*(args[1]) == 0) {
945 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
946 err_code |= ERR_ALERT | ERR_FATAL;
947 goto out;
948 }
949 global.tune.pipesize = atol(args[1]);
950 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100951 else if (!strcmp(args[0], "tune.http.cookielen")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200952 if (alertif_too_many_args(1, file, linenum, args, &err_code))
953 goto out;
Willy Tarreau193b8c62012-11-22 00:17:38 +0100954 if (*(args[1]) == 0) {
955 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
956 err_code |= ERR_ALERT | ERR_FATAL;
957 goto out;
958 }
959 global.tune.cookie_len = atol(args[1]) + 1;
960 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200961 else if (!strcmp(args[0], "tune.http.maxhdr")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200962 if (alertif_too_many_args(1, file, linenum, args, &err_code))
963 goto out;
Willy Tarreauac1932d2011-10-24 19:14:41 +0200964 if (*(args[1]) == 0) {
965 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
966 err_code |= ERR_ALERT | ERR_FATAL;
967 goto out;
968 }
969 global.tune.max_http_hdr = atol(args[1]);
970 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100971 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
972#ifdef USE_ZLIB
William Lallemand1a748ae2015-05-19 16:37:23 +0200973 if (alertif_too_many_args(1, file, linenum, args, &err_code))
974 goto out;
William Lallemanda509e4c2012-11-07 16:54:34 +0100975 if (*args[1]) {
976 global.tune.zlibmemlevel = atoi(args[1]);
977 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
978 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
979 file, linenum, args[0]);
980 err_code |= ERR_ALERT | ERR_FATAL;
981 goto out;
982 }
983 } else {
984 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
985 file, linenum, args[0]);
986 err_code |= ERR_ALERT | ERR_FATAL;
987 goto out;
988 }
989#else
990 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
991 err_code |= ERR_ALERT | ERR_FATAL;
992 goto out;
993#endif
994 }
995 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
996#ifdef USE_ZLIB
William Lallemand1a748ae2015-05-19 16:37:23 +0200997 if (alertif_too_many_args(1, file, linenum, args, &err_code))
998 goto out;
William Lallemanda509e4c2012-11-07 16:54:34 +0100999 if (*args[1]) {
1000 global.tune.zlibwindowsize = atoi(args[1]);
1001 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
1002 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
1003 file, linenum, args[0]);
1004 err_code |= ERR_ALERT | ERR_FATAL;
1005 goto out;
1006 }
1007 } else {
1008 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
1009 file, linenum, args[0]);
1010 err_code |= ERR_ALERT | ERR_FATAL;
1011 goto out;
1012 }
1013#else
1014 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1015 err_code |= ERR_ALERT | ERR_FATAL;
1016 goto out;
1017#endif
1018 }
William Lallemandf3747832012-11-09 12:33:10 +01001019 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001020 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1021 goto out;
William Lallemandf3747832012-11-09 12:33:10 +01001022 if (*args[1]) {
1023 global.tune.comp_maxlevel = atoi(args[1]);
1024 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
1025 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1026 file, linenum, args[0]);
1027 err_code |= ERR_ALERT | ERR_FATAL;
1028 goto out;
1029 }
1030 } else {
1031 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1032 file, linenum, args[0]);
1033 err_code |= ERR_ALERT | ERR_FATAL;
1034 goto out;
1035 }
1036 }
Willy Tarreauf3045d22015-04-29 16:24:50 +02001037 else if (!strcmp(args[0], "tune.pattern.cache-size")) {
1038 if (*args[1]) {
1039 global.tune.pattern_cache = atoi(args[1]);
1040 if (global.tune.pattern_cache < 0) {
1041 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
1042 file, linenum, args[0]);
1043 err_code |= ERR_ALERT | ERR_FATAL;
1044 goto out;
1045 }
1046 } else {
1047 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
1048 file, linenum, args[0]);
1049 err_code |= ERR_ALERT | ERR_FATAL;
1050 goto out;
1051 }
1052 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001053 else if (!strcmp(args[0], "uid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001054 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1055 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001056 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001057 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001058 err_code |= ERR_ALERT;
1059 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001060 }
1061 if (*(args[1]) == 0) {
1062 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001063 err_code |= ERR_ALERT | ERR_FATAL;
1064 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001065 }
1066 global.uid = atol(args[1]);
1067 }
1068 else if (!strcmp(args[0], "gid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001069 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1070 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001071 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001072 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001073 err_code |= ERR_ALERT;
1074 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001075 }
1076 if (*(args[1]) == 0) {
1077 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001078 err_code |= ERR_ALERT | ERR_FATAL;
1079 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001080 }
1081 global.gid = atol(args[1]);
1082 }
Simon Horman98637e52014-06-20 12:30:16 +09001083 else if (!strcmp(args[0], "external-check")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001084 if (alertif_too_many_args(0, file, linenum, args, &err_code))
1085 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09001086 global.external_check = 1;
1087 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001088 /* user/group name handling */
1089 else if (!strcmp(args[0], "user")) {
1090 struct passwd *ha_user;
William Lallemand1a748ae2015-05-19 16:37:23 +02001091 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1092 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001093 if (global.uid != 0) {
1094 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001095 err_code |= ERR_ALERT;
1096 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001097 }
1098 errno = 0;
1099 ha_user = getpwnam(args[1]);
1100 if (ha_user != NULL) {
1101 global.uid = (int)ha_user->pw_uid;
1102 }
1103 else {
1104 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 +02001105 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001106 }
1107 }
1108 else if (!strcmp(args[0], "group")) {
1109 struct group *ha_group;
William Lallemand1a748ae2015-05-19 16:37:23 +02001110 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1111 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001112 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02001113 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001114 err_code |= ERR_ALERT;
1115 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001116 }
1117 errno = 0;
1118 ha_group = getgrnam(args[1]);
1119 if (ha_group != NULL) {
1120 global.gid = (int)ha_group->gr_gid;
1121 }
1122 else {
1123 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 +02001124 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001125 }
1126 }
1127 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +02001128 else if (!strcmp(args[0], "nbproc")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001129 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1130 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001131 if (*(args[1]) == 0) {
1132 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001133 err_code |= ERR_ALERT | ERR_FATAL;
1134 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001135 }
1136 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001137 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
1138 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
1139 file, linenum, args[0], LONGBITS, global.nbproc);
1140 err_code |= ERR_ALERT | ERR_FATAL;
1141 goto out;
1142 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001143 }
1144 else if (!strcmp(args[0], "maxconn")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001145 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1146 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001147 if (global.maxconn != 0) {
1148 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001149 err_code |= ERR_ALERT;
1150 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001151 }
1152 if (*(args[1]) == 0) {
1153 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001154 err_code |= ERR_ALERT | ERR_FATAL;
1155 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001156 }
1157 global.maxconn = atol(args[1]);
1158#ifdef SYSTEM_MAXCONN
1159 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
1160 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);
1161 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +02001162 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001163 }
1164#endif /* SYSTEM_MAXCONN */
1165 }
Willy Tarreau403edff2012-09-06 11:58:37 +02001166 else if (!strcmp(args[0], "maxsslconn")) {
1167#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001168 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1169 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001170 if (*(args[1]) == 0) {
1171 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1172 err_code |= ERR_ALERT | ERR_FATAL;
1173 goto out;
1174 }
1175 global.maxsslconn = atol(args[1]);
1176#else
Emeric Brun0914df82012-10-02 18:45:42 +02001177 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1178 err_code |= ERR_ALERT | ERR_FATAL;
1179 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001180#endif
1181 }
Willy Tarreau610f04b2014-02-13 11:36:41 +01001182 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
1183#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001184 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1185 goto out;
Willy Tarreau610f04b2014-02-13 11:36:41 +01001186 if (*(args[1]) == 0) {
1187 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1188 err_code |= ERR_ALERT | ERR_FATAL;
1189 goto out;
1190 }
1191 free(global.listen_default_ciphers);
1192 global.listen_default_ciphers = strdup(args[1]);
1193#else
1194 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1195 err_code |= ERR_ALERT | ERR_FATAL;
1196 goto out;
1197#endif
1198 }
1199 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
1200#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001201 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1202 goto out;
Willy Tarreau610f04b2014-02-13 11:36:41 +01001203 if (*(args[1]) == 0) {
1204 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1205 err_code |= ERR_ALERT | ERR_FATAL;
1206 goto out;
1207 }
1208 free(global.connect_default_ciphers);
1209 global.connect_default_ciphers = strdup(args[1]);
1210#else
1211 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1212 err_code |= ERR_ALERT | ERR_FATAL;
1213 goto out;
1214#endif
1215 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02001216#ifdef USE_OPENSSL
1217#ifndef OPENSSL_NO_DH
1218 else if (!strcmp(args[0], "ssl-dh-param-file")) {
1219 if (*(args[1]) == 0) {
1220 Alert("parsing [%s:%d] : '%s' expects a file path as an argument.\n", file, linenum, args[0]);
1221 err_code |= ERR_ALERT | ERR_FATAL;
1222 goto out;
1223 }
1224 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
1225 Alert("parsing [%s:%d] : '%s': unable to load DH parameters from file <%s>.\n", file, linenum, args[0], args[1]);
1226 err_code |= ERR_ALERT | ERR_FATAL;
1227 goto out;
1228 }
1229 }
1230#endif
1231#endif
Emeric Brun850efd52014-01-29 12:24:34 +01001232 else if (!strcmp(args[0], "ssl-server-verify")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001233 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1234 goto out;
Emeric Brun850efd52014-01-29 12:24:34 +01001235 if (*(args[1]) == 0) {
1236 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1237 err_code |= ERR_ALERT | ERR_FATAL;
1238 goto out;
1239 }
1240 if (strcmp(args[1],"none") == 0)
1241 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1242 else if (strcmp(args[1],"required") == 0)
1243 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1244 else {
1245 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1246 err_code |= ERR_ALERT | ERR_FATAL;
1247 goto out;
1248 }
1249 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001250 else if (!strcmp(args[0], "maxconnrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001251 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1252 goto out;
Willy Tarreau81c25d02011-09-07 15:17:21 +02001253 if (global.cps_lim != 0) {
1254 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1255 err_code |= ERR_ALERT;
1256 goto out;
1257 }
1258 if (*(args[1]) == 0) {
1259 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1260 err_code |= ERR_ALERT | ERR_FATAL;
1261 goto out;
1262 }
1263 global.cps_lim = atol(args[1]);
1264 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001265 else if (!strcmp(args[0], "maxsessrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001266 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1267 goto out;
Willy Tarreau93e7c002013-10-07 18:51:07 +02001268 if (global.sps_lim != 0) {
1269 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1270 err_code |= ERR_ALERT;
1271 goto out;
1272 }
1273 if (*(args[1]) == 0) {
1274 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1275 err_code |= ERR_ALERT | ERR_FATAL;
1276 goto out;
1277 }
1278 global.sps_lim = atol(args[1]);
1279 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001280 else if (!strcmp(args[0], "maxsslrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001281 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1282 goto out;
Willy Tarreaue43d5322013-10-07 20:01:52 +02001283 if (global.ssl_lim != 0) {
1284 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1285 err_code |= ERR_ALERT;
1286 goto out;
1287 }
1288 if (*(args[1]) == 0) {
1289 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1290 err_code |= ERR_ALERT | ERR_FATAL;
1291 goto out;
1292 }
1293 global.ssl_lim = atol(args[1]);
1294 }
William Lallemandd85f9172012-11-09 17:05:39 +01001295 else if (!strcmp(args[0], "maxcomprate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001296 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1297 goto out;
William Lallemandd85f9172012-11-09 17:05:39 +01001298 if (*(args[1]) == 0) {
1299 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1300 err_code |= ERR_ALERT | ERR_FATAL;
1301 goto out;
1302 }
1303 global.comp_rate_lim = atoi(args[1]) * 1024;
1304 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001305 else if (!strcmp(args[0], "maxpipes")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001306 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1307 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001308 if (global.maxpipes != 0) {
1309 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001310 err_code |= ERR_ALERT;
1311 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001312 }
1313 if (*(args[1]) == 0) {
1314 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001315 err_code |= ERR_ALERT | ERR_FATAL;
1316 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001317 }
1318 global.maxpipes = atol(args[1]);
1319 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001320 else if (!strcmp(args[0], "maxzlibmem")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001321 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1322 goto out;
William Lallemand9d5f5482012-11-07 16:12:57 +01001323 if (*(args[1]) == 0) {
1324 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1325 err_code |= ERR_ALERT | ERR_FATAL;
1326 goto out;
1327 }
William Lallemande3a7d992012-11-20 11:25:20 +01001328 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001329 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001330 else if (!strcmp(args[0], "maxcompcpuusage")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001331 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1332 goto out;
William Lallemand072a2bf2012-11-20 17:01:01 +01001333 if (*(args[1]) == 0) {
1334 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1335 err_code |= ERR_ALERT | ERR_FATAL;
1336 goto out;
1337 }
1338 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001339 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001340 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1341 err_code |= ERR_ALERT | ERR_FATAL;
1342 goto out;
1343 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001344 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001345
Willy Tarreaubaaee002006-06-26 02:48:02 +02001346 else if (!strcmp(args[0], "ulimit-n")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001347 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1348 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001349 if (global.rlimit_nofile != 0) {
1350 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001351 err_code |= ERR_ALERT;
1352 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001353 }
1354 if (*(args[1]) == 0) {
1355 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001356 err_code |= ERR_ALERT | ERR_FATAL;
1357 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001358 }
1359 global.rlimit_nofile = atol(args[1]);
1360 }
1361 else if (!strcmp(args[0], "chroot")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001362 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1363 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001364 if (global.chroot != NULL) {
1365 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001366 err_code |= ERR_ALERT;
1367 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001368 }
1369 if (*(args[1]) == 0) {
1370 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001371 err_code |= ERR_ALERT | ERR_FATAL;
1372 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001373 }
1374 global.chroot = strdup(args[1]);
1375 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001376 else if (!strcmp(args[0], "description")) {
1377 int i, len=0;
1378 char *d;
1379
1380 if (!*args[1]) {
1381 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1382 file, linenum, args[0]);
1383 err_code |= ERR_ALERT | ERR_FATAL;
1384 goto out;
1385 }
1386
Willy Tarreau348acfe2014-04-14 15:00:39 +02001387 for (i = 1; *args[i]; i++)
1388 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001389
1390 if (global.desc)
1391 free(global.desc);
1392
1393 global.desc = d = (char *)calloc(1, len);
1394
Willy Tarreau348acfe2014-04-14 15:00:39 +02001395 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1396 for (i = 2; *args[i]; i++)
1397 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001398 }
1399 else if (!strcmp(args[0], "node")) {
1400 int i;
1401 char c;
1402
William Lallemand1a748ae2015-05-19 16:37:23 +02001403 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1404 goto out;
1405
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001406 for (i=0; args[1][i]; i++) {
1407 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001408 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1409 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001410 break;
1411 }
1412
1413 if (!i || args[1][i]) {
1414 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1415 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1416 file, linenum, args[0]);
1417 err_code |= ERR_ALERT | ERR_FATAL;
1418 goto out;
1419 }
1420
1421 if (global.node)
1422 free(global.node);
1423
1424 global.node = strdup(args[1]);
1425 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001426 else if (!strcmp(args[0], "pidfile")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001427 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1428 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001429 if (global.pidfile != NULL) {
1430 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001431 err_code |= ERR_ALERT;
1432 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001433 }
1434 if (*(args[1]) == 0) {
1435 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001436 err_code |= ERR_ALERT | ERR_FATAL;
1437 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001438 }
1439 global.pidfile = strdup(args[1]);
1440 }
Emeric Bruned760922010-10-22 17:59:25 +02001441 else if (!strcmp(args[0], "unix-bind")) {
1442 int cur_arg = 1;
1443 while (*(args[cur_arg])) {
1444 if (!strcmp(args[cur_arg], "prefix")) {
1445 if (global.unix_bind.prefix != NULL) {
1446 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1447 err_code |= ERR_ALERT;
1448 cur_arg += 2;
1449 continue;
1450 }
1451
1452 if (*(args[cur_arg+1]) == 0) {
1453 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1454 err_code |= ERR_ALERT | ERR_FATAL;
1455 goto out;
1456 }
1457 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1458 cur_arg += 2;
1459 continue;
1460 }
1461
1462 if (!strcmp(args[cur_arg], "mode")) {
1463
1464 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1465 cur_arg += 2;
1466 continue;
1467 }
1468
1469 if (!strcmp(args[cur_arg], "uid")) {
1470
1471 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1472 cur_arg += 2;
1473 continue;
1474 }
1475
1476 if (!strcmp(args[cur_arg], "gid")) {
1477
1478 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1479 cur_arg += 2;
1480 continue;
1481 }
1482
1483 if (!strcmp(args[cur_arg], "user")) {
1484 struct passwd *user;
1485
1486 user = getpwnam(args[cur_arg + 1]);
1487 if (!user) {
1488 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1489 file, linenum, args[0], args[cur_arg + 1 ]);
1490 err_code |= ERR_ALERT | ERR_FATAL;
1491 goto out;
1492 }
1493
1494 global.unix_bind.ux.uid = user->pw_uid;
1495 cur_arg += 2;
1496 continue;
1497 }
1498
1499 if (!strcmp(args[cur_arg], "group")) {
1500 struct group *group;
1501
1502 group = getgrnam(args[cur_arg + 1]);
1503 if (!group) {
1504 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1505 file, linenum, args[0], args[cur_arg + 1 ]);
1506 err_code |= ERR_ALERT | ERR_FATAL;
1507 goto out;
1508 }
1509
1510 global.unix_bind.ux.gid = group->gr_gid;
1511 cur_arg += 2;
1512 continue;
1513 }
1514
Willy Tarreaub48f9582011-09-05 01:17:06 +02001515 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001516 file, linenum, args[0]);
1517 err_code |= ERR_ALERT | ERR_FATAL;
1518 goto out;
1519 }
1520 }
William Lallemand0f99e342011-10-12 17:50:54 +02001521 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1522 /* delete previous herited or defined syslog servers */
1523 struct logsrv *back;
1524 struct logsrv *tmp;
1525
1526 if (*(args[1]) != 0) {
1527 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1528 err_code |= ERR_ALERT | ERR_FATAL;
1529 goto out;
1530 }
1531
1532 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1533 LIST_DEL(&tmp->list);
1534 free(tmp);
1535 }
1536 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001537 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001538 struct sockaddr_storage *sk;
1539 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001540 struct logsrv *logsrv;
Willy Tarreau18324f52014-06-27 18:10:07 +02001541 int arg = 0;
1542 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001543
William Lallemand1a748ae2015-05-19 16:37:23 +02001544 if (alertif_too_many_args(8, file, linenum, args, &err_code)) /* does not strictly check optional arguments */
1545 goto out;
1546
Willy Tarreaubaaee002006-06-26 02:48:02 +02001547 if (*(args[1]) == 0 || *(args[2]) == 0) {
1548 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001549 err_code |= ERR_ALERT | ERR_FATAL;
1550 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001551 }
William Lallemand0f99e342011-10-12 17:50:54 +02001552
1553 logsrv = calloc(1, sizeof(struct logsrv));
1554
Willy Tarreau18324f52014-06-27 18:10:07 +02001555 /* just after the address, a length may be specified */
1556 if (strcmp(args[arg+2], "len") == 0) {
1557 len = atoi(args[arg+3]);
1558 if (len < 80 || len > 65535) {
1559 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1560 file, linenum, args[arg+3]);
1561 err_code |= ERR_ALERT | ERR_FATAL;
1562 goto out;
1563 }
1564 logsrv->maxlen = len;
1565
1566 /* skip these two args */
1567 arg += 2;
1568 }
1569 else
1570 logsrv->maxlen = MAX_SYSLOG_LEN;
1571
1572 if (logsrv->maxlen > global.max_syslog_len) {
1573 global.max_syslog_len = logsrv->maxlen;
1574 logline = realloc(logline, global.max_syslog_len + 1);
1575 }
1576
William Lallemand1a748ae2015-05-19 16:37:23 +02001577 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
1578 goto out;
1579
Willy Tarreau18324f52014-06-27 18:10:07 +02001580 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001581 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001582 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001583 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001584 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001585 }
1586
William Lallemand0f99e342011-10-12 17:50:54 +02001587 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02001588 if (*(args[arg+3])) {
1589 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001590 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001591 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001592 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001593 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001594 }
1595 }
1596
William Lallemand0f99e342011-10-12 17:50:54 +02001597 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02001598 if (*(args[arg+4])) {
1599 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001600 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001601 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001602 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001603 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001604 }
1605 }
1606
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02001607 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001608 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001609 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001610 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001611 free(logsrv);
1612 goto out;
1613 }
1614 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001615
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001616 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001617 if (port1 != port2) {
1618 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1619 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001620 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001621 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001622 goto out;
1623 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001624
William Lallemand0f99e342011-10-12 17:50:54 +02001625 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001626 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001627 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001628 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001629
William Lallemand0f99e342011-10-12 17:50:54 +02001630 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001631 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001632 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1633 char *name;
1634 int len;
1635
1636 if (global.log_send_hostname != NULL) {
1637 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1638 err_code |= ERR_ALERT;
1639 goto out;
1640 }
1641
1642 if (*(args[1]))
1643 name = args[1];
1644 else
1645 name = hostname;
1646
1647 len = strlen(name);
1648
1649 /* We'll add a space after the name to respect the log format */
1650 free(global.log_send_hostname);
1651 global.log_send_hostname = malloc(len + 2);
1652 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1653 }
Baptiste Assmann6bc89362015-08-23 09:22:25 +02001654 else if (!strcmp(args[0], "server-state-base")) { /* path base where HAProxy can find server state files */
1655 if (global.server_state_base != NULL) {
1656 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1657 err_code |= ERR_ALERT;
1658 goto out;
1659 }
1660
1661 if (!*(args[1])) {
1662 Alert("parsing [%s:%d] : '%s' expects one argument: a directory path.\n", file, linenum, args[0]);
1663 err_code |= ERR_FATAL;
1664 goto out;
1665 }
1666
1667 global.server_state_base = strdup(args[1]);
1668 }
Baptiste Assmanne0882262015-08-23 09:54:31 +02001669 else if (!strcmp(args[0], "server-state-file")) { /* path to the file where HAProxy can load the server states */
1670 if (global.server_state_file != NULL) {
1671 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1672 err_code |= ERR_ALERT;
1673 goto out;
1674 }
1675
1676 if (!*(args[1])) {
1677 Alert("parsing [%s:%d] : '%s' expect one argument: a file path.\n", file, linenum, args[0]);
1678 err_code |= ERR_FATAL;
1679 goto out;
1680 }
1681
1682 global.server_state_file = strdup(args[1]);
1683 }
Kevinm48936af2010-12-22 16:08:21 +00001684 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
William Lallemand1a748ae2015-05-19 16:37:23 +02001685 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1686 goto out;
Kevinm48936af2010-12-22 16:08:21 +00001687 if (*(args[1]) == 0) {
1688 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1689 err_code |= ERR_ALERT | ERR_FATAL;
1690 goto out;
1691 }
1692 free(global.log_tag);
1693 global.log_tag = strdup(args[1]);
1694 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001695 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
William Lallemand1a748ae2015-05-19 16:37:23 +02001696 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1697 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001698 if (global.spread_checks != 0) {
1699 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001700 err_code |= ERR_ALERT;
1701 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001702 }
1703 if (*(args[1]) == 0) {
1704 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001705 err_code |= ERR_ALERT | ERR_FATAL;
1706 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001707 }
1708 global.spread_checks = atol(args[1]);
1709 if (global.spread_checks < 0 || global.spread_checks > 50) {
1710 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001711 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001712 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001713 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001714 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1715 const char *err;
1716 unsigned int val;
1717
William Lallemand1a748ae2015-05-19 16:37:23 +02001718 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1719 goto out;
Willy Tarreau1746eec2014-04-25 10:46:47 +02001720 if (*(args[1]) == 0) {
1721 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1722 err_code |= ERR_ALERT | ERR_FATAL;
1723 goto out;
1724 }
1725
1726 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1727 if (err) {
1728 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1729 err_code |= ERR_ALERT | ERR_FATAL;
1730 }
1731 global.max_spread_checks = val;
1732 if (global.max_spread_checks < 0) {
1733 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1734 err_code |= ERR_ALERT | ERR_FATAL;
1735 }
1736 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001737 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1738#ifdef USE_CPU_AFFINITY
1739 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001740 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001741 unsigned long cpus = 0;
1742
1743 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001744 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001745 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001746 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001747 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001748 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001749 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001750 proc = atol(args[1]);
1751 if (proc >= 1 && proc <= LONGBITS)
1752 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001753 }
1754
1755 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001756 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",
1757 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001758 err_code |= ERR_ALERT | ERR_FATAL;
1759 goto out;
1760 }
1761
1762 cur_arg = 2;
1763 while (*args[cur_arg]) {
1764 unsigned int low, high;
1765
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001766 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001767 char *dash = strchr(args[cur_arg], '-');
1768
1769 low = high = str2uic(args[cur_arg]);
1770 if (dash)
1771 high = str2uic(dash + 1);
1772
1773 if (high < low) {
1774 unsigned int swap = low;
1775 low = high;
1776 high = swap;
1777 }
1778
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001779 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001780 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001781 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001782 err_code |= ERR_ALERT | ERR_FATAL;
1783 goto out;
1784 }
1785
1786 while (low <= high)
1787 cpus |= 1UL << low++;
1788 }
1789 else {
1790 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1791 file, linenum, args[0], args[cur_arg]);
1792 err_code |= ERR_ALERT | ERR_FATAL;
1793 goto out;
1794 }
1795 cur_arg++;
1796 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001797 for (i = 0; i < LONGBITS; i++)
1798 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001799 global.cpu_map[i] = cpus;
1800#else
1801 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1802 err_code |= ERR_ALERT | ERR_FATAL;
1803 goto out;
1804#endif
1805 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001806 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001807 struct cfg_kw_list *kwl;
1808 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001809 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001810
1811 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1812 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1813 if (kwl->kw[index].section != CFG_GLOBAL)
1814 continue;
1815 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001816 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001817 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001818 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001819 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001820 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001821 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001822 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001823 err_code |= ERR_WARN;
1824 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001825 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001826 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001827 }
1828 }
1829 }
1830
Willy Tarreaubaaee002006-06-26 02:48:02 +02001831 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001832 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001833 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001834
Willy Tarreau058e9072009-07-20 09:30:05 +02001835 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001836 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001837 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001838}
1839
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001840void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001841{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001842 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001843 defproxy.mode = PR_MODE_TCP;
1844 defproxy.state = PR_STNEW;
1845 defproxy.maxconn = cfg_maxpconn;
1846 defproxy.conn_retries = CONN_RETRIES;
Joseph Lynch726ab712015-05-11 23:25:34 -07001847 defproxy.redispatch_after = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001848
Simon Horman66183002013-02-23 10:16:43 +09001849 defproxy.defsrv.check.inter = DEF_CHKINTR;
1850 defproxy.defsrv.check.fastinter = 0;
1851 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001852 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1853 defproxy.defsrv.agent.fastinter = 0;
1854 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001855 defproxy.defsrv.check.rise = DEF_RISETIME;
1856 defproxy.defsrv.check.fall = DEF_FALLTIME;
1857 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1858 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001859 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001860 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001861 defproxy.defsrv.maxqueue = 0;
1862 defproxy.defsrv.minconn = 0;
1863 defproxy.defsrv.maxconn = 0;
1864 defproxy.defsrv.slowstart = 0;
1865 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1866 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1867 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Simon Horman64e34162015-02-06 11:11:57 +09001868
1869 defproxy.email_alert.level = LOG_ALERT;
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02001870 defproxy.load_server_state_from_file = PR_SRV_STATE_FILE_UNSPEC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001871}
1872
Willy Tarreauade5ec42010-01-28 19:33:49 +01001873
Willy Tarreau63af98d2014-05-18 08:11:41 +02001874/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1875 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1876 * ERR_FATAL in case of error.
1877 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001878static int create_cond_regex_rule(const char *file, int line,
1879 struct proxy *px, int dir, int action, int flags,
1880 const char *cmd, const char *reg, const char *repl,
1881 const char **cond_start)
1882{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001883 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001884 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001885 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001886 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001887 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001888 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001889 int cs;
1890 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001891
1892 if (px == &defproxy) {
1893 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001894 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001895 goto err;
1896 }
1897
1898 if (*reg == 0) {
1899 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001900 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001901 goto err;
1902 }
1903
1904 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001905 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001906
Willy Tarreau5321c422010-01-28 20:35:13 +01001907 if (cond_start &&
1908 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001909 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1910 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1911 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001912 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001913 goto err;
1914 }
1915 }
1916 else if (cond_start && **cond_start) {
1917 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1918 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001919 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001920 goto err;
1921 }
1922
Willy Tarreau63af98d2014-05-18 08:11:41 +02001923 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001924 (dir == SMP_OPT_DIR_REQ) ?
1925 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1926 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1927 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001928
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001929 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001930 if (!preg) {
1931 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001932 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001933 goto err;
1934 }
1935
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001936 cs = !(flags & REG_ICASE);
1937 cap = !(flags & REG_NOSUB);
1938 error = NULL;
1939 if (!regex_comp(reg, preg, cs, cap, &error)) {
1940 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1941 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001942 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001943 goto err;
1944 }
1945
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001946 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001947 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001948 if (repl && err) {
1949 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1950 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001951 ret_code |= ERR_ALERT | ERR_FATAL;
1952 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001953 }
1954
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001955 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001956 ret_code |= ERR_WARN;
1957
1958 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001959
Willy Tarreau63af98d2014-05-18 08:11:41 +02001960 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001961 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001962 err:
1963 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001964 free(errmsg);
1965 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001966}
1967
Willy Tarreaubaaee002006-06-26 02:48:02 +02001968/*
William Lallemand51097192015-04-14 16:35:22 +02001969 * Parse a line in a <listen>, <frontend> or <backend> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001970 * Returns the error code, 0 if OK, or any combination of :
1971 * - ERR_ABORT: must abort ASAP
1972 * - ERR_FATAL: we can continue parsing but not start the service
1973 * - ERR_WARN: a warning has been emitted
1974 * - ERR_ALERT: an alert has been emitted
1975 * Only the two first ones can stop processing, the two others are just
1976 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001977 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001978int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1979{
1980 static struct peers *curpeers = NULL;
1981 struct peer *newpeer = NULL;
1982 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001983 struct bind_conf *bind_conf;
1984 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001985 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001986 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001987
1988 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001989 if (!*args[1]) {
1990 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001991 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001992 goto out;
1993 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001994
William Lallemand6e62fb62015-04-28 16:55:23 +02001995 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1996 goto out;
1997
Emeric Brun32da3c42010-09-23 18:39:19 +02001998 err = invalid_char(args[1]);
1999 if (err) {
2000 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2001 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01002002 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002003 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002004 }
2005
2006 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
2007 /*
2008 * If there are two proxies with the same name only following
2009 * combinations are allowed:
2010 */
2011 if (strcmp(curpeers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002012 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 +02002013 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002014 err_code |= ERR_ALERT | ERR_FATAL;
Emeric Brun32da3c42010-09-23 18:39:19 +02002015 }
2016 }
2017
2018 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
2019 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2020 err_code |= ERR_ALERT | ERR_ABORT;
2021 goto out;
2022 }
2023
2024 curpeers->next = peers;
2025 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002026 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002027 curpeers->conf.line = linenum;
2028 curpeers->last_change = now.tv_sec;
2029 curpeers->id = strdup(args[1]);
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002030 curpeers->state = PR_STNEW;
Emeric Brun32da3c42010-09-23 18:39:19 +02002031 }
2032 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01002033 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01002034 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002035 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02002036
2037 if (!*args[2]) {
2038 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2039 file, linenum, args[0]);
2040 err_code |= ERR_ALERT | ERR_FATAL;
2041 goto out;
2042 }
2043
2044 err = invalid_char(args[1]);
2045 if (err) {
2046 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2047 file, linenum, *err, args[1]);
2048 err_code |= ERR_ALERT | ERR_FATAL;
2049 goto out;
2050 }
2051
2052 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
2053 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2054 err_code |= ERR_ALERT | ERR_ABORT;
2055 goto out;
2056 }
2057
2058 /* the peers are linked backwards first */
2059 curpeers->count++;
2060 newpeer->next = curpeers->remote;
2061 curpeers->remote = newpeer;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002062 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002063 newpeer->conf.line = linenum;
2064
2065 newpeer->last_change = now.tv_sec;
2066 newpeer->id = strdup(args[1]);
2067
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002068 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002069 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01002070 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002071 err_code |= ERR_ALERT | ERR_FATAL;
2072 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002073 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01002074
2075 proto = protocol_by_family(sk->ss_family);
2076 if (!proto || !proto->connect) {
2077 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2078 file, linenum, args[0], args[1]);
2079 err_code |= ERR_ALERT | ERR_FATAL;
2080 goto out;
2081 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002082
2083 if (port1 != port2) {
2084 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2085 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002086 err_code |= ERR_ALERT | ERR_FATAL;
2087 goto out;
2088 }
2089
Willy Tarreau2aa38802013-02-20 19:20:59 +01002090 if (!port1) {
2091 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2092 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002093 err_code |= ERR_ALERT | ERR_FATAL;
2094 goto out;
2095 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002096
Emeric Brun32da3c42010-09-23 18:39:19 +02002097 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002098 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002099 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02002100 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02002101
Emeric Brun32da3c42010-09-23 18:39:19 +02002102 if (strcmp(newpeer->id, localpeer) == 0) {
2103 /* Current is local peer, it define a frontend */
2104 newpeer->local = 1;
Emeric Brunb3971ab2015-05-12 18:49:09 +02002105 peers->local = newpeer;
Emeric Brun32da3c42010-09-23 18:39:19 +02002106
2107 if (!curpeers->peers_fe) {
2108 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
2109 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2110 err_code |= ERR_ALERT | ERR_ABORT;
2111 goto out;
2112 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002113
Willy Tarreau237250c2011-07-29 01:49:03 +02002114 init_new_proxy(curpeers->peers_fe);
2115 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02002116 curpeers->peers_fe->id = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002117 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
2118 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau91d96282015-03-13 15:47:26 +01002119 peers_setup_frontend(curpeers->peers_fe);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002120
2121 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
2122
Willy Tarreau902636f2013-03-10 19:44:48 +01002123 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
2124 if (errmsg && *errmsg) {
2125 indent_msg(&errmsg, 2);
2126 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002127 }
2128 else
2129 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
2130 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002131 err_code |= ERR_FATAL;
2132 goto out;
2133 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02002134
2135 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01002136 l->maxaccept = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002137 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
2138 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
Willy Tarreau9903f0e2015-04-04 18:50:31 +02002139 l->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02002140 l->handler = process_stream;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002141 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01002142 l->default_target = ((struct proxy *)curpeers->peers_fe)->default_target;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002143 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
2144 global.maxsock += l->maxconn;
2145 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002146 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01002147 else {
2148 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
2149 file, linenum, args[0], args[1],
2150 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
2151 err_code |= ERR_FATAL;
2152 goto out;
2153 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002154 }
2155 } /* neither "peer" nor "peers" */
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002156 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
2157 curpeers->state = PR_STSTOPPED;
2158 }
2159 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
2160 curpeers->state = PR_STNEW;
2161 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002162 else if (*args[0] != 0) {
2163 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2164 err_code |= ERR_ALERT | ERR_FATAL;
2165 goto out;
2166 }
2167
2168out:
Willy Tarreau902636f2013-03-10 19:44:48 +01002169 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02002170 return err_code;
2171}
2172
Baptiste Assmann325137d2015-04-13 23:40:55 +02002173/*
2174 * Parse a <resolvers> section.
2175 * Returns the error code, 0 if OK, or any combination of :
2176 * - ERR_ABORT: must abort ASAP
2177 * - ERR_FATAL: we can continue parsing but not start the service
2178 * - ERR_WARN: a warning has been emitted
2179 * - ERR_ALERT: an alert has been emitted
2180 * Only the two first ones can stop processing, the two others are just
2181 * indicators.
2182 */
2183int cfg_parse_resolvers(const char *file, int linenum, char **args, int kwm)
2184{
2185 static struct dns_resolvers *curr_resolvers = NULL;
2186 struct dns_nameserver *newnameserver = NULL;
2187 const char *err;
2188 int err_code = 0;
2189 char *errmsg = NULL;
2190
2191 if (strcmp(args[0], "resolvers") == 0) { /* new resolvers section */
2192 if (!*args[1]) {
2193 Alert("parsing [%s:%d] : missing name for resolvers section.\n", file, linenum);
2194 err_code |= ERR_ALERT | ERR_ABORT;
2195 goto out;
2196 }
2197
2198 err = invalid_char(args[1]);
2199 if (err) {
2200 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2201 file, linenum, *err, args[0], args[1]);
2202 err_code |= ERR_ALERT | ERR_ABORT;
2203 goto out;
2204 }
2205
2206 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
2207 /* Error if two resolvers owns the same name */
2208 if (strcmp(curr_resolvers->id, args[1]) == 0) {
2209 Alert("Parsing [%s:%d]: resolvers '%s' has same name as another resolvers (declared at %s:%d).\n",
2210 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2211 err_code |= ERR_ALERT | ERR_ABORT;
2212 }
2213 }
2214
2215 if ((curr_resolvers = (struct dns_resolvers *)calloc(1, sizeof(struct dns_resolvers))) == NULL) {
2216 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2217 err_code |= ERR_ALERT | ERR_ABORT;
2218 goto out;
2219 }
2220
2221 /* default values */
2222 LIST_ADDQ(&dns_resolvers, &curr_resolvers->list);
2223 curr_resolvers->conf.file = strdup(file);
2224 curr_resolvers->conf.line = linenum;
2225 curr_resolvers->id = strdup(args[1]);
2226 curr_resolvers->query_ids = EB_ROOT;
2227 /* default hold period for valid is 10s */
Baptiste Assmann4c5490a2015-07-14 21:42:49 +02002228 curr_resolvers->hold.valid = 10000;
2229 curr_resolvers->timeout.retry = 1000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002230 curr_resolvers->resolve_retries = 3;
2231 LIST_INIT(&curr_resolvers->nameserver_list);
2232 LIST_INIT(&curr_resolvers->curr_resolution);
2233 }
2234 else if (strcmp(args[0], "nameserver") == 0) { /* nameserver definition */
2235 struct sockaddr_storage *sk;
2236 int port1, port2;
2237 struct protocol *proto;
2238
2239 if (!*args[2]) {
2240 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2241 file, linenum, args[0]);
2242 err_code |= ERR_ALERT | ERR_FATAL;
2243 goto out;
2244 }
2245
2246 err = invalid_char(args[1]);
2247 if (err) {
2248 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2249 file, linenum, *err, args[1]);
2250 err_code |= ERR_ALERT | ERR_FATAL;
2251 goto out;
2252 }
2253
2254 if ((newnameserver = (struct dns_nameserver *)calloc(1, sizeof(struct dns_nameserver))) == NULL) {
2255 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2256 err_code |= ERR_ALERT | ERR_ABORT;
2257 goto out;
2258 }
2259
2260 /* the nameservers are linked backward first */
2261 LIST_ADDQ(&curr_resolvers->nameserver_list, &newnameserver->list);
2262 curr_resolvers->count_nameservers++;
2263 newnameserver->resolvers = curr_resolvers;
2264 newnameserver->conf.file = strdup(file);
2265 newnameserver->conf.line = linenum;
2266 newnameserver->id = strdup(args[1]);
2267
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002268 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002269 if (!sk) {
2270 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2271 err_code |= ERR_ALERT | ERR_FATAL;
2272 goto out;
2273 }
2274
2275 proto = protocol_by_family(sk->ss_family);
2276 if (!proto || !proto->connect) {
2277 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2278 file, linenum, args[0], args[1]);
2279 err_code |= ERR_ALERT | ERR_FATAL;
2280 goto out;
2281 }
2282
2283 if (port1 != port2) {
2284 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2285 file, linenum, args[0], args[1], args[2]);
2286 err_code |= ERR_ALERT | ERR_FATAL;
2287 goto out;
2288 }
2289
2290 newnameserver->addr = *sk;
2291 }
2292 else if (strcmp(args[0], "hold") == 0) { /* hold periods */
2293 const char *res;
2294 unsigned int time;
2295
2296 if (!*args[2]) {
2297 Alert("parsing [%s:%d] : '%s' expects an <event> and a <time> as arguments.\n",
2298 file, linenum, args[0]);
2299 Alert("<event> can be either 'valid', 'nx', 'refused', 'timeout', or 'other'\n");
2300 err_code |= ERR_ALERT | ERR_FATAL;
2301 goto out;
2302 }
2303 res = parse_time_err(args[2], &time, TIME_UNIT_MS);
2304 if (res) {
2305 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2306 file, linenum, *res, args[0]);
2307 err_code |= ERR_ALERT | ERR_FATAL;
2308 goto out;
2309 }
2310 if (strcmp(args[1], "valid") == 0)
2311 curr_resolvers->hold.valid = time;
2312 else {
2313 Alert("parsing [%s:%d] : '%s' unknown <event>: '%s', expects 'valid'\n",
2314 file, linenum, args[0], args[1]);
2315 err_code |= ERR_ALERT | ERR_FATAL;
2316 goto out;
2317 }
2318
2319 }
2320 else if (strcmp(args[0], "resolve_retries") == 0) {
2321 if (!*args[1]) {
2322 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2323 file, linenum, args[0]);
2324 err_code |= ERR_ALERT | ERR_FATAL;
2325 goto out;
2326 }
2327 curr_resolvers->resolve_retries = atoi(args[1]);
2328 }
2329 else if (strcmp(args[0], "timeout") == 0) {
2330 const char *res;
2331 unsigned int timeout_retry;
2332
2333 if (!*args[2]) {
2334 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments.\n",
2335 file, linenum, args[0]);
2336 err_code |= ERR_ALERT | ERR_FATAL;
2337 goto out;
2338 }
2339 res = parse_time_err(args[2], &timeout_retry, TIME_UNIT_MS);
2340 if (res) {
2341 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2342 file, linenum, *res, args[0]);
2343 err_code |= ERR_ALERT | ERR_FATAL;
2344 goto out;
2345 }
2346 curr_resolvers->timeout.retry = timeout_retry;
2347 } /* neither "nameserver" nor "resolvers" */
2348 else if (*args[0] != 0) {
2349 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2350 err_code |= ERR_ALERT | ERR_FATAL;
2351 goto out;
2352 }
2353
2354 out:
2355 free(errmsg);
2356 return err_code;
2357}
Simon Horman0d16a402015-01-30 11:22:58 +09002358
2359/*
William Lallemand51097192015-04-14 16:35:22 +02002360 * Parse a line in a <listen>, <frontend> or <backend> section.
Simon Horman0d16a402015-01-30 11:22:58 +09002361 * Returns the error code, 0 if OK, or any combination of :
2362 * - ERR_ABORT: must abort ASAP
2363 * - ERR_FATAL: we can continue parsing but not start the service
2364 * - ERR_WARN: a warning has been emitted
2365 * - ERR_ALERT: an alert has been emitted
2366 * Only the two first ones can stop processing, the two others are just
2367 * indicators.
2368 */
2369int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
2370{
2371 static struct mailers *curmailers = NULL;
2372 struct mailer *newmailer = NULL;
2373 const char *err;
2374 int err_code = 0;
2375 char *errmsg = NULL;
2376
2377 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
2378 if (!*args[1]) {
2379 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
2380 err_code |= ERR_ALERT | ERR_ABORT;
2381 goto out;
2382 }
2383
2384 err = invalid_char(args[1]);
2385 if (err) {
2386 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2387 file, linenum, *err, args[0], args[1]);
2388 err_code |= ERR_ALERT | ERR_ABORT;
2389 goto out;
2390 }
2391
2392 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
2393 /*
2394 * If there are two proxies with the same name only following
2395 * combinations are allowed:
2396 */
2397 if (strcmp(curmailers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002398 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 +09002399 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002400 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman0d16a402015-01-30 11:22:58 +09002401 }
2402 }
2403
2404 if ((curmailers = (struct mailers *)calloc(1, sizeof(struct mailers))) == NULL) {
2405 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2406 err_code |= ERR_ALERT | ERR_ABORT;
2407 goto out;
2408 }
2409
2410 curmailers->next = mailers;
2411 mailers = curmailers;
2412 curmailers->conf.file = strdup(file);
2413 curmailers->conf.line = linenum;
2414 curmailers->id = strdup(args[1]);
2415 }
2416 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
2417 struct sockaddr_storage *sk;
2418 int port1, port2;
2419 struct protocol *proto;
2420
2421 if (!*args[2]) {
2422 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2423 file, linenum, args[0]);
2424 err_code |= ERR_ALERT | ERR_FATAL;
2425 goto out;
2426 }
2427
2428 err = invalid_char(args[1]);
2429 if (err) {
2430 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2431 file, linenum, *err, args[1]);
2432 err_code |= ERR_ALERT | ERR_FATAL;
2433 goto out;
2434 }
2435
2436 if ((newmailer = (struct mailer *)calloc(1, sizeof(struct mailer))) == NULL) {
2437 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2438 err_code |= ERR_ALERT | ERR_ABORT;
2439 goto out;
2440 }
2441
2442 /* the mailers are linked backwards first */
2443 curmailers->count++;
2444 newmailer->next = curmailers->mailer_list;
2445 curmailers->mailer_list = newmailer;
2446 newmailer->mailers = curmailers;
2447 newmailer->conf.file = strdup(file);
2448 newmailer->conf.line = linenum;
2449
2450 newmailer->id = strdup(args[1]);
2451
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002452 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Simon Horman0d16a402015-01-30 11:22:58 +09002453 if (!sk) {
2454 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2455 err_code |= ERR_ALERT | ERR_FATAL;
2456 goto out;
2457 }
2458
2459 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002460 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2461 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002462 file, linenum, args[0], args[1]);
2463 err_code |= ERR_ALERT | ERR_FATAL;
2464 goto out;
2465 }
2466
2467 if (port1 != port2) {
2468 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2469 file, linenum, args[0], args[1], args[2]);
2470 err_code |= ERR_ALERT | ERR_FATAL;
2471 goto out;
2472 }
2473
2474 if (!port1) {
2475 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2476 file, linenum, args[0], args[1], args[2]);
2477 err_code |= ERR_ALERT | ERR_FATAL;
2478 goto out;
2479 }
2480
2481 newmailer->addr = *sk;
2482 newmailer->proto = proto;
2483 newmailer->xprt = &raw_sock;
2484 newmailer->sock_init_arg = NULL;
2485 } /* neither "mailer" nor "mailers" */
2486 else if (*args[0] != 0) {
2487 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2488 err_code |= ERR_ALERT | ERR_FATAL;
2489 goto out;
2490 }
2491
2492out:
2493 free(errmsg);
2494 return err_code;
2495}
2496
Simon Horman9dc49962015-01-30 11:22:59 +09002497static void free_email_alert(struct proxy *p)
2498{
2499 free(p->email_alert.mailers.name);
2500 p->email_alert.mailers.name = NULL;
2501 free(p->email_alert.from);
2502 p->email_alert.from = NULL;
2503 free(p->email_alert.to);
2504 p->email_alert.to = NULL;
2505 free(p->email_alert.myhostname);
2506 p->email_alert.myhostname = NULL;
2507}
2508
Willy Tarreau3842f002009-06-14 11:39:52 +02002509int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002510{
2511 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002512 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002513 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002514 int rc;
2515 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002516 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002517 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002518 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002519 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002520 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002521
Willy Tarreau977b8e42006-12-29 14:19:17 +01002522 if (!strcmp(args[0], "listen"))
2523 rc = PR_CAP_LISTEN;
2524 else if (!strcmp(args[0], "frontend"))
2525 rc = PR_CAP_FE | PR_CAP_RS;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02002526 else if (!strcmp(args[0], "backend"))
Willy Tarreau977b8e42006-12-29 14:19:17 +01002527 rc = PR_CAP_BE | PR_CAP_RS;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002528 else
2529 rc = PR_CAP_NONE;
2530
2531 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002532 if (!*args[1]) {
2533 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
2534 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
2535 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002536 err_code |= ERR_ALERT | ERR_ABORT;
2537 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002538 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002539
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002540 err = invalid_char(args[1]);
2541 if (err) {
2542 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2543 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002544 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002545 }
2546
Willy Tarreau8f50b682015-05-26 11:45:02 +02002547 curproxy = (rc & PR_CAP_FE) ? proxy_fe_by_name(args[1]) : proxy_be_by_name(args[1]);
2548 if (curproxy) {
2549 Alert("Parsing [%s:%d]: %s '%s' has the same name as %s '%s' declared at %s:%d.\n",
2550 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2551 curproxy->id, curproxy->conf.file, curproxy->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002552 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002553 }
2554
Willy Tarreaubaaee002006-06-26 02:48:02 +02002555 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
2556 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002557 err_code |= ERR_ALERT | ERR_ABORT;
2558 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002559 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002560
Willy Tarreau97cb7802010-01-03 20:23:58 +01002561 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002562 curproxy->next = proxy;
2563 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002564 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2565 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002566 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002567 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002568 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002569 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002570
William Lallemand6e62fb62015-04-28 16:55:23 +02002571 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2572 if (curproxy->cap & PR_CAP_FE)
2573 Alert("parsing [%s:%d] : please use the 'bind' keyword for listening addresses.\n", file, linenum);
2574 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002575 }
2576
2577 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002578 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002579 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002580
Willy Tarreaubaaee002006-06-26 02:48:02 +02002581 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002582 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002583 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002584 curproxy->no_options = defproxy.no_options;
2585 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002586 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002587 curproxy->except_net = defproxy.except_net;
2588 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002589 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002590 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002591
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002592 if (defproxy.fwdfor_hdr_len) {
2593 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2594 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2595 }
2596
Willy Tarreaub86db342009-11-30 11:50:16 +01002597 if (defproxy.orgto_hdr_len) {
2598 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2599 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2600 }
2601
Mark Lamourinec2247f02012-01-04 13:02:01 -05002602 if (defproxy.server_id_hdr_len) {
2603 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2604 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2605 }
2606
Willy Tarreau977b8e42006-12-29 14:19:17 +01002607 if (curproxy->cap & PR_CAP_FE) {
2608 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002609 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002610 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002611
2612 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002613 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2614 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002615
2616 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2617 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002618
Willy Tarreau977b8e42006-12-29 14:19:17 +01002619 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002620 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002621 curproxy->fullconn = defproxy.fullconn;
2622 curproxy->conn_retries = defproxy.conn_retries;
Joseph Lynch726ab712015-05-11 23:25:34 -07002623 curproxy->redispatch_after = defproxy.redispatch_after;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002624 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002625
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002626 if (defproxy.check_req) {
2627 curproxy->check_req = calloc(1, defproxy.check_len);
2628 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2629 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002630 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002631
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002632 if (defproxy.expect_str) {
2633 curproxy->expect_str = strdup(defproxy.expect_str);
2634 if (defproxy.expect_regex) {
2635 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002636 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2637 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002638 }
2639 }
2640
Willy Tarreau67402132012-05-31 20:40:20 +02002641 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002642 if (defproxy.cookie_name)
2643 curproxy->cookie_name = strdup(defproxy.cookie_name);
2644 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002645 if (defproxy.cookie_domain)
2646 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002647
Willy Tarreau31936852010-10-06 16:59:56 +02002648 if (defproxy.cookie_maxidle)
2649 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2650
2651 if (defproxy.cookie_maxlife)
2652 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2653
Emeric Brun647caf12009-06-30 17:57:00 +02002654 if (defproxy.rdp_cookie_name)
2655 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2656 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2657
Willy Tarreau01732802007-11-01 22:48:15 +01002658 if (defproxy.url_param_name)
2659 curproxy->url_param_name = strdup(defproxy.url_param_name);
2660 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002661
Benoitaffb4812009-03-25 13:02:10 +01002662 if (defproxy.hh_name)
2663 curproxy->hh_name = strdup(defproxy.hh_name);
2664 curproxy->hh_len = defproxy.hh_len;
2665 curproxy->hh_match_domain = defproxy.hh_match_domain;
2666
Willy Tarreauef9a3602012-12-08 22:29:20 +01002667 if (defproxy.conn_src.iface_name)
2668 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2669 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002670 curproxy->conn_src.opts = defproxy.conn_src.opts;
Willy Tarreau29fbe512015-08-20 19:35:14 +02002671#if defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002672 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002673#endif
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02002674 curproxy->load_server_state_from_file = defproxy.load_server_state_from_file;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002675 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002676
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002677 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002678 if (defproxy.capture_name)
2679 curproxy->capture_name = strdup(defproxy.capture_name);
2680 curproxy->capture_namelen = defproxy.capture_namelen;
2681 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002682 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002683
Willy Tarreau977b8e42006-12-29 14:19:17 +01002684 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002685 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002686 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002687 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002688 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002689 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002690 curproxy->mon_net = defproxy.mon_net;
2691 curproxy->mon_mask = defproxy.mon_mask;
2692 if (defproxy.monitor_uri)
2693 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2694 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002695 if (defproxy.defbe.name)
2696 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002697
2698 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002699 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2700 if (curproxy->conf.logformat_string &&
2701 curproxy->conf.logformat_string != default_http_log_format &&
2702 curproxy->conf.logformat_string != default_tcp_log_format &&
2703 curproxy->conf.logformat_string != clf_http_log_format)
2704 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2705
2706 if (defproxy.conf.lfs_file) {
2707 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2708 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2709 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002710 }
2711
2712 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002713 curproxy->timeout.connect = defproxy.timeout.connect;
2714 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002715 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002716 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002717 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002718 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002719 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002720 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002721 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002722 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002723 }
2724
Willy Tarreaubaaee002006-06-26 02:48:02 +02002725 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002726 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002727
2728 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002729 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002730 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002731 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002732 LIST_INIT(&node->list);
2733 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2734 }
2735
Willy Tarreau62a61232013-04-12 18:13:46 +02002736 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2737 if (curproxy->conf.uniqueid_format_string)
2738 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2739
Willy Tarreau094af4e2015-01-07 15:03:42 +01002740 if (defproxy.log_tag)
2741 curproxy->log_tag = strdup(defproxy.log_tag);
2742
Willy Tarreau62a61232013-04-12 18:13:46 +02002743 if (defproxy.conf.uif_file) {
2744 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2745 curproxy->conf.uif_line = defproxy.conf.uif_line;
2746 }
William Lallemanda73203e2012-03-12 12:48:57 +01002747
2748 /* copy default header unique id */
2749 if (defproxy.header_unique_id)
2750 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2751
William Lallemand82fe75c2012-10-23 10:25:10 +02002752 /* default compression options */
2753 if (defproxy.comp != NULL) {
2754 curproxy->comp = calloc(1, sizeof(struct comp));
2755 curproxy->comp->algos = defproxy.comp->algos;
2756 curproxy->comp->types = defproxy.comp->types;
2757 }
2758
Willy Tarreaubaaee002006-06-26 02:48:02 +02002759 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002760 curproxy->conf.used_listener_id = EB_ROOT;
2761 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002762
Simon Horman98637e52014-06-20 12:30:16 +09002763 if (defproxy.check_path)
2764 curproxy->check_path = strdup(defproxy.check_path);
2765 if (defproxy.check_command)
2766 curproxy->check_command = strdup(defproxy.check_command);
2767
Simon Horman9dc49962015-01-30 11:22:59 +09002768 if (defproxy.email_alert.mailers.name)
2769 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2770 if (defproxy.email_alert.from)
2771 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2772 if (defproxy.email_alert.to)
2773 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2774 if (defproxy.email_alert.myhostname)
2775 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09002776 curproxy->email_alert.level = defproxy.email_alert.level;
Simon Horman9dc49962015-01-30 11:22:59 +09002777
Willy Tarreau93893792009-07-23 13:19:11 +02002778 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002779 }
2780 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2781 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002782 /* FIXME-20070101: we should do this too at the end of the
2783 * config parsing to free all default values.
2784 */
William Lallemand6e62fb62015-04-28 16:55:23 +02002785 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2786 err_code |= ERR_ABORT;
2787 goto out;
2788 }
2789
Willy Tarreaua534fea2008-08-03 12:19:50 +02002790 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002791 free(defproxy.check_command);
2792 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002793 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002794 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002795 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002796 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002797 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002798 free(defproxy.capture_name);
2799 free(defproxy.monitor_uri);
2800 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002801 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002802 free(defproxy.fwdfor_hdr_name);
2803 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002804 free(defproxy.orgto_hdr_name);
2805 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002806 free(defproxy.server_id_hdr_name);
2807 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002808 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002809 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002810 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002811 free(defproxy.expect_regex);
2812 defproxy.expect_regex = NULL;
2813 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002814
Willy Tarreau62a61232013-04-12 18:13:46 +02002815 if (defproxy.conf.logformat_string != default_http_log_format &&
2816 defproxy.conf.logformat_string != default_tcp_log_format &&
2817 defproxy.conf.logformat_string != clf_http_log_format)
2818 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002819
Willy Tarreau62a61232013-04-12 18:13:46 +02002820 free(defproxy.conf.uniqueid_format_string);
2821 free(defproxy.conf.lfs_file);
2822 free(defproxy.conf.uif_file);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002823 free(defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09002824 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02002825
Willy Tarreaua534fea2008-08-03 12:19:50 +02002826 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002827 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002828
Willy Tarreaubaaee002006-06-26 02:48:02 +02002829 /* we cannot free uri_auth because it might already be used */
2830 init_default_instance();
2831 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002832 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2833 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002834 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002835 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002836 }
2837 else if (curproxy == NULL) {
2838 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002839 err_code |= ERR_ALERT | ERR_FATAL;
2840 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002841 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002842
2843 /* update the current file and line being parsed */
2844 curproxy->conf.args.file = curproxy->conf.file;
2845 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002846
2847 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002848 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2849 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2850 if (err_code & ERR_FATAL)
2851 goto out;
2852 }
2853 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002854 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002855 int cur_arg;
2856
Willy Tarreaubaaee002006-06-26 02:48:02 +02002857 if (curproxy == &defproxy) {
2858 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002859 err_code |= ERR_ALERT | ERR_FATAL;
2860 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002861 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002862 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002863 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002864
Willy Tarreau24709282013-03-10 21:32:12 +01002865 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002866 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002867 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002868 err_code |= ERR_ALERT | ERR_FATAL;
2869 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002870 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002871
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002872 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002873
2874 /* use default settings for unix sockets */
2875 bind_conf->ux.uid = global.unix_bind.ux.uid;
2876 bind_conf->ux.gid = global.unix_bind.ux.gid;
2877 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002878
2879 /* NOTE: the following line might create several listeners if there
2880 * are comma-separated IPs or port ranges. So all further processing
2881 * will have to be applied to all listeners created after last_listen.
2882 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002883 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2884 if (errmsg && *errmsg) {
2885 indent_msg(&errmsg, 2);
2886 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002887 }
2888 else
2889 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2890 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002891 err_code |= ERR_ALERT | ERR_FATAL;
2892 goto out;
2893 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002894
Willy Tarreau4348fad2012-09-20 16:48:07 +02002895 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2896 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002897 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002898 }
2899
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002900 cur_arg = 2;
2901 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002902 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002903 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002904 char *err;
2905
Willy Tarreau26982662012-09-12 23:17:10 +02002906 kw = bind_find_kw(args[cur_arg]);
2907 if (kw) {
2908 char *err = NULL;
2909 int code;
2910
2911 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002912 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2913 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002914 cur_arg += 1 + kw->skip ;
2915 err_code |= ERR_ALERT | ERR_FATAL;
2916 goto out;
2917 }
2918
Willy Tarreau4348fad2012-09-20 16:48:07 +02002919 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002920 err_code |= code;
2921
2922 if (code) {
2923 if (err && *err) {
2924 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002925 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002926 }
2927 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002928 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2929 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002930 if (code & ERR_FATAL) {
2931 free(err);
2932 cur_arg += 1 + kw->skip;
2933 goto out;
2934 }
2935 }
2936 free(err);
2937 cur_arg += 1 + kw->skip;
2938 continue;
2939 }
2940
Willy Tarreau8638f482012-09-18 18:01:17 +02002941 err = NULL;
2942 if (!bind_dumped) {
2943 bind_dump_kws(&err);
2944 indent_msg(&err, 4);
2945 bind_dumped = 1;
2946 }
2947
2948 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2949 file, linenum, args[0], args[1], args[cur_arg],
2950 err ? " Registered keywords :" : "", err ? err : "");
2951 free(err);
2952
Willy Tarreau93893792009-07-23 13:19:11 +02002953 err_code |= ERR_ALERT | ERR_FATAL;
2954 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002955 }
Willy Tarreau93893792009-07-23 13:19:11 +02002956 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002957 }
2958 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002959 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002960 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2961 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002962 err_code |= ERR_ALERT | ERR_FATAL;
2963 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002964 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002965 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002966 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002967
Willy Tarreaubaaee002006-06-26 02:48:02 +02002968 /* flush useless bits */
2969 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002970 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002971 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002972 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002973 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002974 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002975
William Lallemanddf1425a2015-04-28 20:17:49 +02002976 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2977 goto out;
2978
Willy Tarreau1c47f852006-07-09 08:22:27 +02002979 if (!*args[1]) {
2980 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2981 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002982 err_code |= ERR_ALERT | ERR_FATAL;
2983 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002984 }
2985
Willy Tarreaua534fea2008-08-03 12:19:50 +02002986 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002987 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002988 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002989 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002990 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2991
Willy Tarreau93893792009-07-23 13:19:11 +02002992 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002993 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002994 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
William Lallemanddf1425a2015-04-28 20:17:49 +02002995 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2996 goto out;
2997
Willy Tarreaubaaee002006-06-26 02:48:02 +02002998 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2999 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
3000 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
3001 else {
3002 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003003 err_code |= ERR_ALERT | ERR_FATAL;
3004 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003005 }
3006 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003007 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003008 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003009
3010 if (curproxy == &defproxy) {
3011 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3012 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003013 err_code |= ERR_ALERT | ERR_FATAL;
3014 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003015 }
3016
William Lallemanddf1425a2015-04-28 20:17:49 +02003017 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3018 goto out;
3019
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003020 if (!*args[1]) {
3021 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3022 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003023 err_code |= ERR_ALERT | ERR_FATAL;
3024 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003025 }
3026
3027 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003028 curproxy->conf.id.key = curproxy->uuid;
Willy Tarreau0d1fdf72015-05-27 16:44:02 +02003029 curproxy->options |= PR_O_FORCED_ID;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003030
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003031 if (curproxy->uuid <= 0) {
3032 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003033 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003034 err_code |= ERR_ALERT | ERR_FATAL;
3035 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003036 }
3037
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003038 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
3039 if (node) {
3040 struct proxy *target = container_of(node, struct proxy, conf.id);
3041 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
3042 file, linenum, proxy_type_str(curproxy), curproxy->id,
3043 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
3044 err_code |= ERR_ALERT | ERR_FATAL;
3045 goto out;
3046 }
3047 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003048 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003049 else if (!strcmp(args[0], "description")) {
3050 int i, len=0;
3051 char *d;
3052
Cyril Bonté99ed3272010-01-24 23:29:44 +01003053 if (curproxy == &defproxy) {
3054 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3055 file, linenum, args[0]);
3056 err_code |= ERR_ALERT | ERR_FATAL;
3057 goto out;
3058 }
3059
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003060 if (!*args[1]) {
3061 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
3062 file, linenum, args[0]);
3063 return -1;
3064 }
3065
Willy Tarreau348acfe2014-04-14 15:00:39 +02003066 for (i = 1; *args[i]; i++)
3067 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003068
3069 d = (char *)calloc(1, len);
3070 curproxy->desc = d;
3071
Willy Tarreau348acfe2014-04-14 15:00:39 +02003072 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
3073 for (i = 2; *args[i]; i++)
3074 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003075
3076 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003077 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
William Lallemanddf1425a2015-04-28 20:17:49 +02003078 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3079 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003080 curproxy->state = PR_STSTOPPED;
3081 }
3082 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
William Lallemanddf1425a2015-04-28 20:17:49 +02003083 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3084 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003085 curproxy->state = PR_STNEW;
3086 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003087 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
3088 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003089 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003090
3091 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003092 unsigned int low, high;
3093
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003094 if (strcmp(args[cur_arg], "all") == 0) {
3095 set = 0;
3096 break;
3097 }
3098 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003099 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003100 }
3101 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003102 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003103 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01003104 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003105 char *dash = strchr(args[cur_arg], '-');
3106
3107 low = high = str2uic(args[cur_arg]);
3108 if (dash)
3109 high = str2uic(dash + 1);
3110
3111 if (high < low) {
3112 unsigned int swap = low;
3113 low = high;
3114 high = swap;
3115 }
3116
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003117 if (low < 1 || high > LONGBITS) {
3118 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
3119 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02003120 err_code |= ERR_ALERT | ERR_FATAL;
3121 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003122 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01003123 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003124 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003125 }
3126 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003127 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
3128 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003129 err_code |= ERR_ALERT | ERR_FATAL;
3130 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003131 }
3132 cur_arg++;
3133 }
3134 curproxy->bind_proc = set;
3135 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003136 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02003137 if (curproxy == &defproxy) {
3138 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003139 err_code |= ERR_ALERT | ERR_FATAL;
3140 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003141 }
3142
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003143 err = invalid_char(args[1]);
3144 if (err) {
3145 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
3146 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003147 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003148 }
3149
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01003150 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003151 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
3152 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003153 err_code |= ERR_ALERT | ERR_FATAL;
3154 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003155 }
3156 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003157 else if (!strcmp(args[0], "cookie")) { /* cookie name */
3158 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003159
Willy Tarreau977b8e42006-12-29 14:19:17 +01003160 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003161 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003162
Willy Tarreaubaaee002006-06-26 02:48:02 +02003163 if (*(args[1]) == 0) {
3164 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
3165 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003166 err_code |= ERR_ALERT | ERR_FATAL;
3167 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003168 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003169
Willy Tarreau67402132012-05-31 20:40:20 +02003170 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003171 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01003172 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003173 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003174 curproxy->cookie_name = strdup(args[1]);
3175 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003176
Willy Tarreaubaaee002006-06-26 02:48:02 +02003177 cur_arg = 2;
3178 while (*(args[cur_arg])) {
3179 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003180 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003181 }
3182 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003183 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003184 }
3185 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003186 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003187 }
3188 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003189 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003190 }
3191 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003192 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003193 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003194 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003195 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003196 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003197 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003198 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003199 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02003200 else if (!strcmp(args[cur_arg], "httponly")) {
3201 curproxy->ck_opts |= PR_CK_HTTPONLY;
3202 }
3203 else if (!strcmp(args[cur_arg], "secure")) {
3204 curproxy->ck_opts |= PR_CK_SECURE;
3205 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003206 else if (!strcmp(args[cur_arg], "domain")) {
3207 if (!*args[cur_arg + 1]) {
3208 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
3209 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003210 err_code |= ERR_ALERT | ERR_FATAL;
3211 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003212 }
3213
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003214 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003215 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003216 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
3217 " dots nor does not start with a dot."
3218 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003219 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003220 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003221 }
3222
3223 err = invalid_domainchar(args[cur_arg + 1]);
3224 if (err) {
3225 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
3226 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003227 err_code |= ERR_ALERT | ERR_FATAL;
3228 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003229 }
3230
Willy Tarreau68a897b2009-12-03 23:28:34 +01003231 if (!curproxy->cookie_domain) {
3232 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
3233 } else {
3234 /* one domain was already specified, add another one by
3235 * building the string which will be returned along with
3236 * the cookie.
3237 */
3238 char *new_ptr;
3239 int new_len = strlen(curproxy->cookie_domain) +
3240 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
3241 new_ptr = malloc(new_len);
3242 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
3243 free(curproxy->cookie_domain);
3244 curproxy->cookie_domain = new_ptr;
3245 }
Willy Tarreau31936852010-10-06 16:59:56 +02003246 cur_arg++;
3247 }
3248 else if (!strcmp(args[cur_arg], "maxidle")) {
3249 unsigned int maxidle;
3250 const char *res;
3251
3252 if (!*args[cur_arg + 1]) {
3253 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
3254 file, linenum, args[cur_arg]);
3255 err_code |= ERR_ALERT | ERR_FATAL;
3256 goto out;
3257 }
3258
3259 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
3260 if (res) {
3261 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3262 file, linenum, *res, args[cur_arg]);
3263 err_code |= ERR_ALERT | ERR_FATAL;
3264 goto out;
3265 }
3266 curproxy->cookie_maxidle = maxidle;
3267 cur_arg++;
3268 }
3269 else if (!strcmp(args[cur_arg], "maxlife")) {
3270 unsigned int maxlife;
3271 const char *res;
3272
3273 if (!*args[cur_arg + 1]) {
3274 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
3275 file, linenum, args[cur_arg]);
3276 err_code |= ERR_ALERT | ERR_FATAL;
3277 goto out;
3278 }
3279
3280 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
3281 if (res) {
3282 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3283 file, linenum, *res, args[cur_arg]);
3284 err_code |= ERR_ALERT | ERR_FATAL;
3285 goto out;
3286 }
3287 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003288 cur_arg++;
3289 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003290 else {
Willy Tarreau31936852010-10-06 16:59:56 +02003291 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache', 'postonly', 'domain', 'maxidle, and 'maxlife' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003292 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003293 err_code |= ERR_ALERT | ERR_FATAL;
3294 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003295 }
3296 cur_arg++;
3297 }
Willy Tarreau67402132012-05-31 20:40:20 +02003298 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003299 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
3300 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003301 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003302 }
3303
Willy Tarreau67402132012-05-31 20:40:20 +02003304 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003305 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
3306 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003307 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003308 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003309
Willy Tarreau67402132012-05-31 20:40:20 +02003310 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003311 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
3312 file, linenum);
3313 err_code |= ERR_ALERT | ERR_FATAL;
3314 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003315 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09003316 else if (!strcmp(args[0], "email-alert")) {
3317 if (*(args[1]) == 0) {
3318 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3319 file, linenum, args[0]);
3320 err_code |= ERR_ALERT | ERR_FATAL;
3321 goto out;
3322 }
3323
3324 if (!strcmp(args[1], "from")) {
3325 if (*(args[1]) == 0) {
3326 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3327 file, linenum, args[1]);
3328 err_code |= ERR_ALERT | ERR_FATAL;
3329 goto out;
3330 }
3331 free(curproxy->email_alert.from);
3332 curproxy->email_alert.from = strdup(args[2]);
3333 }
3334 else if (!strcmp(args[1], "mailers")) {
3335 if (*(args[1]) == 0) {
3336 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3337 file, linenum, args[1]);
3338 err_code |= ERR_ALERT | ERR_FATAL;
3339 goto out;
3340 }
3341 free(curproxy->email_alert.mailers.name);
3342 curproxy->email_alert.mailers.name = strdup(args[2]);
3343 }
3344 else if (!strcmp(args[1], "myhostname")) {
3345 if (*(args[1]) == 0) {
3346 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3347 file, linenum, args[1]);
3348 err_code |= ERR_ALERT | ERR_FATAL;
3349 goto out;
3350 }
3351 free(curproxy->email_alert.myhostname);
3352 curproxy->email_alert.myhostname = strdup(args[2]);
3353 }
Simon Horman64e34162015-02-06 11:11:57 +09003354 else if (!strcmp(args[1], "level")) {
3355 curproxy->email_alert.level = get_log_level(args[2]);
3356 if (curproxy->email_alert.level < 0) {
3357 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
3358 file, linenum, args[1], args[2]);
3359 err_code |= ERR_ALERT | ERR_FATAL;
3360 goto out;
3361 }
3362 }
Simon Horman9dc49962015-01-30 11:22:59 +09003363 else if (!strcmp(args[1], "to")) {
3364 if (*(args[1]) == 0) {
3365 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3366 file, linenum, args[1]);
3367 err_code |= ERR_ALERT | ERR_FATAL;
3368 goto out;
3369 }
3370 free(curproxy->email_alert.to);
3371 curproxy->email_alert.to = strdup(args[2]);
3372 }
3373 else {
3374 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
3375 file, linenum, args[1]);
3376 err_code |= ERR_ALERT | ERR_FATAL;
3377 goto out;
3378 }
Simon Horman64e34162015-02-06 11:11:57 +09003379 /* Indicate that the email_alert is at least partially configured */
3380 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09003381 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09003382 else if (!strcmp(args[0], "external-check")) {
3383 if (*(args[1]) == 0) {
3384 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3385 file, linenum, args[0]);
3386 err_code |= ERR_ALERT | ERR_FATAL;
3387 goto out;
3388 }
3389
3390 if (!strcmp(args[1], "command")) {
William Lallemanddf1425a2015-04-28 20:17:49 +02003391 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3392 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09003393 if (*(args[1]) == 0) {
3394 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3395 file, linenum, args[1]);
3396 err_code |= ERR_ALERT | ERR_FATAL;
3397 goto out;
3398 }
3399 free(curproxy->check_command);
3400 curproxy->check_command = strdup(args[2]);
3401 }
3402 else if (!strcmp(args[1], "path")) {
William Lallemanddf1425a2015-04-28 20:17:49 +02003403 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3404 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09003405 if (*(args[1]) == 0) {
3406 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3407 file, linenum, args[1]);
3408 err_code |= ERR_ALERT | ERR_FATAL;
3409 goto out;
3410 }
3411 free(curproxy->check_path);
3412 curproxy->check_path = strdup(args[2]);
3413 }
3414 else {
3415 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
3416 file, linenum, args[1]);
3417 err_code |= ERR_ALERT | ERR_FATAL;
3418 goto out;
3419 }
3420 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02003421 else if (!strcmp(args[0], "persist")) { /* persist */
3422 if (*(args[1]) == 0) {
3423 Alert("parsing [%s:%d] : missing persist method.\n",
3424 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003425 err_code |= ERR_ALERT | ERR_FATAL;
3426 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003427 }
3428
3429 if (!strncmp(args[1], "rdp-cookie", 10)) {
3430 curproxy->options2 |= PR_O2_RDPC_PRST;
3431
Emeric Brunb982a3d2010-01-04 15:45:53 +01003432 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003433 const char *beg, *end;
3434
3435 beg = args[1] + 11;
3436 end = strchr(beg, ')');
3437
William Lallemanddf1425a2015-04-28 20:17:49 +02003438 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3439 goto out;
3440
Emeric Brun647caf12009-06-30 17:57:00 +02003441 if (!end || end == beg) {
3442 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3443 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003444 err_code |= ERR_ALERT | ERR_FATAL;
3445 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003446 }
3447
3448 free(curproxy->rdp_cookie_name);
3449 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3450 curproxy->rdp_cookie_len = end-beg;
3451 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003452 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003453 free(curproxy->rdp_cookie_name);
3454 curproxy->rdp_cookie_name = strdup("msts");
3455 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3456 }
3457 else { /* syntax */
3458 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3459 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003460 err_code |= ERR_ALERT | ERR_FATAL;
3461 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003462 }
3463 }
3464 else {
3465 Alert("parsing [%s:%d] : unknown persist method.\n",
3466 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003467 err_code |= ERR_ALERT | ERR_FATAL;
3468 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003469 }
3470 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003471 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreau6db62c52015-08-10 19:04:29 +02003472 Alert("parsing [%s:%d] : '%s' is not supported anymore, please check the documentation.\n", file, linenum, args[0]);
3473 err_code |= ERR_ALERT | ERR_FATAL;
3474 goto out;
3475 }
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02003476 else if (!strcmp(args[0], "load-server-state-from-file")) {
3477 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3478 err_code |= ERR_WARN;
3479 if (!strcmp(args[1], "global")) { /* use the file pointed to by global server-state-file directive */
3480 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_GLOBAL;
3481 }
3482 else if (!strcmp(args[1], "local")) { /* use the server-state-file-name variable to locate the server-state file */
3483 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_LOCAL;
3484 }
3485 else if (!strcmp(args[1], "none")) { /* don't use server-state-file directive for this backend */
3486 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
3487 }
3488 else {
3489 Alert("parsing [%s:%d] : '%s' expects 'global', 'local' or 'none'. Got '%s'\n",
3490 file, linenum, args[0], args[1]);
3491 err_code |= ERR_ALERT | ERR_FATAL;
3492 goto out;
3493 }
3494 }
3495 else if (!strcmp(args[0], "server-state-file-name")) {
3496 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3497 err_code |= ERR_WARN;
3498 if (*(args[1]) == 0) {
3499 Alert("parsing [%s:%d] : '%s' expects 'use-backend-name' or a string. Got no argument\n",
3500 file, linenum, args[0]);
3501 err_code |= ERR_ALERT | ERR_FATAL;
3502 goto out;
3503 }
3504 else if (!strcmp(args[1], "use-backend-name"))
3505 curproxy->server_state_file_name = strdup(curproxy->id);
3506 else
3507 curproxy->server_state_file_name = strdup(args[1]);
3508 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003509 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003510 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003511 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003512
Willy Tarreaubaaee002006-06-26 02:48:02 +02003513 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003514 if (curproxy == &defproxy) {
3515 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3516 err_code |= ERR_ALERT | ERR_FATAL;
3517 goto out;
3518 }
3519
William Lallemand1a748ae2015-05-19 16:37:23 +02003520 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3521 goto out;
3522
Willy Tarreaubaaee002006-06-26 02:48:02 +02003523 if (*(args[4]) == 0) {
3524 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3525 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003526 err_code |= ERR_ALERT | ERR_FATAL;
3527 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003528 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003529 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003530 curproxy->capture_name = strdup(args[2]);
3531 curproxy->capture_namelen = strlen(curproxy->capture_name);
3532 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003533 curproxy->to_log |= LW_COOKIE;
3534 }
3535 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3536 struct cap_hdr *hdr;
3537
3538 if (curproxy == &defproxy) {
3539 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 +02003540 err_code |= ERR_ALERT | ERR_FATAL;
3541 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003542 }
3543
William Lallemand1a748ae2015-05-19 16:37:23 +02003544 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3545 goto out;
3546
Willy Tarreaubaaee002006-06-26 02:48:02 +02003547 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3548 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3549 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003550 err_code |= ERR_ALERT | ERR_FATAL;
3551 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003552 }
3553
3554 hdr = calloc(sizeof(struct cap_hdr), 1);
3555 hdr->next = curproxy->req_cap;
3556 hdr->name = strdup(args[3]);
3557 hdr->namelen = strlen(args[3]);
3558 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003559 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003560 hdr->index = curproxy->nb_req_cap++;
3561 curproxy->req_cap = hdr;
3562 curproxy->to_log |= LW_REQHDR;
3563 }
3564 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3565 struct cap_hdr *hdr;
3566
3567 if (curproxy == &defproxy) {
3568 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 +02003569 err_code |= ERR_ALERT | ERR_FATAL;
3570 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003571 }
3572
William Lallemand1a748ae2015-05-19 16:37:23 +02003573 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3574 goto out;
3575
Willy Tarreaubaaee002006-06-26 02:48:02 +02003576 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3577 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3578 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003579 err_code |= ERR_ALERT | ERR_FATAL;
3580 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003581 }
3582 hdr = calloc(sizeof(struct cap_hdr), 1);
3583 hdr->next = curproxy->rsp_cap;
3584 hdr->name = strdup(args[3]);
3585 hdr->namelen = strlen(args[3]);
3586 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003587 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003588 hdr->index = curproxy->nb_rsp_cap++;
3589 curproxy->rsp_cap = hdr;
3590 curproxy->to_log |= LW_RSPHDR;
3591 }
3592 else {
3593 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3594 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003595 err_code |= ERR_ALERT | ERR_FATAL;
3596 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003597 }
3598 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003599 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003600 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003601 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003602
William Lallemanddf1425a2015-04-28 20:17:49 +02003603 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3604 goto out;
3605
Willy Tarreaubaaee002006-06-26 02:48:02 +02003606 if (*(args[1]) == 0) {
3607 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3608 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003609 err_code |= ERR_ALERT | ERR_FATAL;
3610 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003611 }
3612 curproxy->conn_retries = atol(args[1]);
3613 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003614 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003615 struct act_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003616
3617 if (curproxy == &defproxy) {
3618 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3619 err_code |= ERR_ALERT | ERR_FATAL;
3620 goto out;
3621 }
3622
Willy Tarreau20b0de52012-12-24 15:45:22 +01003623 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003624 !LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003625 (LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3626 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_DENY ||
3627 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REDIR ||
3628 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REQ_AUTH)) {
Willy Tarreau20b0de52012-12-24 15:45:22 +01003629 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 +01003630 file, linenum, args[0]);
3631 err_code |= ERR_WARN;
3632 }
3633
Willy Tarreauff011f22011-01-06 17:51:27 +01003634 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003635
Willy Tarreauff011f22011-01-06 17:51:27 +01003636 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003637 err_code |= ERR_ALERT | ERR_ABORT;
3638 goto out;
3639 }
3640
Willy Tarreau5002f572014-04-23 01:32:02 +02003641 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003642 err_code |= warnif_cond_conflicts(rule->cond,
3643 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3644 file, linenum);
3645
Willy Tarreauff011f22011-01-06 17:51:27 +01003646 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003647 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003648 else if (!strcmp(args[0], "http-response")) { /* response access control */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003649 struct act_rule *rule;
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003650
3651 if (curproxy == &defproxy) {
3652 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3653 err_code |= ERR_ALERT | ERR_FATAL;
3654 goto out;
3655 }
3656
3657 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003658 !LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003659 (LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3660 LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_DENY)) {
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003661 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3662 file, linenum, args[0]);
3663 err_code |= ERR_WARN;
3664 }
3665
3666 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3667
3668 if (!rule) {
3669 err_code |= ERR_ALERT | ERR_ABORT;
3670 goto out;
3671 }
3672
3673 err_code |= warnif_cond_conflicts(rule->cond,
3674 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3675 file, linenum);
3676
3677 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3678 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003679 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3680 /* set the header name and length into the proxy structure */
3681 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3682 err_code |= ERR_WARN;
3683
3684 if (!*args[1]) {
3685 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3686 file, linenum, args[0]);
3687 err_code |= ERR_ALERT | ERR_FATAL;
3688 goto out;
3689 }
3690
3691 /* set the desired header name */
3692 free(curproxy->server_id_hdr_name);
3693 curproxy->server_id_hdr_name = strdup(args[1]);
3694 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3695 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003696 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003697 struct act_rule *rule;
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003698
Willy Tarreaub099aca2008-10-12 17:26:37 +02003699 if (curproxy == &defproxy) {
3700 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003701 err_code |= ERR_ALERT | ERR_FATAL;
3702 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003703 }
3704
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003705 /* emulate "block" using "http-request block". Since these rules are supposed to
3706 * be processed before all http-request rules, we put them into their own list
3707 * and will insert them at the end.
3708 */
3709 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3710 if (!rule) {
3711 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003712 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003713 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003714 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3715 err_code |= warnif_cond_conflicts(rule->cond,
3716 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3717 file, linenum);
3718 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003719
3720 if (!already_warned(WARN_BLOCK_DEPRECATED))
3721 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]);
3722
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003723 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003724 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003725 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003726
Cyril Bonté99ed3272010-01-24 23:29:44 +01003727 if (curproxy == &defproxy) {
3728 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3729 err_code |= ERR_ALERT | ERR_FATAL;
3730 goto out;
3731 }
3732
Willy Tarreaube4653b2015-05-28 15:26:58 +02003733 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003734 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3735 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003736 err_code |= ERR_ALERT | ERR_FATAL;
3737 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003738 }
3739
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003740 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003741 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003742 err_code |= warnif_cond_conflicts(rule->cond,
3743 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3744 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003745 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003746 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003747 struct switching_rule *rule;
3748
Willy Tarreaub099aca2008-10-12 17:26:37 +02003749 if (curproxy == &defproxy) {
3750 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003751 err_code |= ERR_ALERT | ERR_FATAL;
3752 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003753 }
3754
Willy Tarreau55ea7572007-06-17 19:56:27 +02003755 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003756 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003757
3758 if (*(args[1]) == 0) {
3759 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003760 err_code |= ERR_ALERT | ERR_FATAL;
3761 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003762 }
3763
Willy Tarreauf51658d2014-04-23 01:21:56 +02003764 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3765 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3766 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3767 file, linenum, errmsg);
3768 err_code |= ERR_ALERT | ERR_FATAL;
3769 goto out;
3770 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003771
Willy Tarreauf51658d2014-04-23 01:21:56 +02003772 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003773 }
3774
3775 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
3776 rule->cond = cond;
3777 rule->be.name = strdup(args[1]);
3778 LIST_INIT(&rule->list);
3779 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3780 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003781 else if (strcmp(args[0], "use-server") == 0) {
3782 struct server_rule *rule;
3783
3784 if (curproxy == &defproxy) {
3785 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3786 err_code |= ERR_ALERT | ERR_FATAL;
3787 goto out;
3788 }
3789
3790 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3791 err_code |= ERR_WARN;
3792
3793 if (*(args[1]) == 0) {
3794 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3795 err_code |= ERR_ALERT | ERR_FATAL;
3796 goto out;
3797 }
3798
3799 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3800 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3801 file, linenum, args[0]);
3802 err_code |= ERR_ALERT | ERR_FATAL;
3803 goto out;
3804 }
3805
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003806 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3807 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3808 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003809 err_code |= ERR_ALERT | ERR_FATAL;
3810 goto out;
3811 }
3812
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003813 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003814
3815 rule = (struct server_rule *)calloc(1, sizeof(*rule));
3816 rule->cond = cond;
3817 rule->srv.name = strdup(args[1]);
3818 LIST_INIT(&rule->list);
3819 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3820 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3821 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003822 else if ((!strcmp(args[0], "force-persist")) ||
3823 (!strcmp(args[0], "ignore-persist"))) {
3824 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003825
3826 if (curproxy == &defproxy) {
3827 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3828 err_code |= ERR_ALERT | ERR_FATAL;
3829 goto out;
3830 }
3831
3832 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3833 err_code |= ERR_WARN;
3834
Willy Tarreauef6494c2010-01-28 17:12:36 +01003835 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003836 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3837 file, linenum, args[0]);
3838 err_code |= ERR_ALERT | ERR_FATAL;
3839 goto out;
3840 }
3841
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003842 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3843 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3844 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003845 err_code |= ERR_ALERT | ERR_FATAL;
3846 goto out;
3847 }
3848
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003849 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3850 * where force-persist is applied.
3851 */
3852 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003853
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003854 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003855 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003856 if (!strcmp(args[0], "force-persist")) {
3857 rule->type = PERSIST_TYPE_FORCE;
3858 } else {
3859 rule->type = PERSIST_TYPE_IGNORE;
3860 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003861 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003862 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003863 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003864 else if (!strcmp(args[0], "stick-table")) {
3865 int myidx = 1;
Willy Tarreaue45288c2015-05-26 10:49:46 +02003866 struct proxy *other;
3867
Willy Tarreaue2dc1fa2015-05-26 12:08:07 +02003868 other = proxy_tbl_by_name(curproxy->id);
Willy Tarreaue45288c2015-05-26 10:49:46 +02003869 if (other) {
3870 Alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
3871 file, linenum, curproxy->id, proxy_type_str(other), other->id, other->conf.file, other->conf.line);
3872 err_code |= ERR_ALERT | ERR_FATAL;
3873 goto out;
3874 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003875
Emeric Brun32da3c42010-09-23 18:39:19 +02003876 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003877 curproxy->table.type = (unsigned int)-1;
3878 while (*args[myidx]) {
3879 const char *err;
3880
3881 if (strcmp(args[myidx], "size") == 0) {
3882 myidx++;
3883 if (!*(args[myidx])) {
3884 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3885 file, linenum, args[myidx-1]);
3886 err_code |= ERR_ALERT | ERR_FATAL;
3887 goto out;
3888 }
3889 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3890 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3891 file, linenum, *err, args[myidx-1]);
3892 err_code |= ERR_ALERT | ERR_FATAL;
3893 goto out;
3894 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003895 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003896 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003897 else if (strcmp(args[myidx], "peers") == 0) {
3898 myidx++;
Godbach50523162013-12-11 19:48:57 +08003899 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003900 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3901 file, linenum, args[myidx-1]);
3902 err_code |= ERR_ALERT | ERR_FATAL;
3903 goto out;
Godbach50523162013-12-11 19:48:57 +08003904 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003905 curproxy->table.peers.name = strdup(args[myidx++]);
3906 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003907 else if (strcmp(args[myidx], "expire") == 0) {
3908 myidx++;
3909 if (!*(args[myidx])) {
3910 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3911 file, linenum, args[myidx-1]);
3912 err_code |= ERR_ALERT | ERR_FATAL;
3913 goto out;
3914 }
3915 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3916 if (err) {
3917 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3918 file, linenum, *err, args[myidx-1]);
3919 err_code |= ERR_ALERT | ERR_FATAL;
3920 goto out;
3921 }
3922 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003923 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003924 }
3925 else if (strcmp(args[myidx], "nopurge") == 0) {
3926 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003927 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003928 }
3929 else if (strcmp(args[myidx], "type") == 0) {
3930 myidx++;
3931 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3932 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3933 file, linenum, args[myidx]);
3934 err_code |= ERR_ALERT | ERR_FATAL;
3935 goto out;
3936 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003937 /* myidx already points to next arg */
3938 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003939 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003940 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003941 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003942
3943 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003944 nw = args[myidx];
3945 while (*nw) {
3946 /* the "store" keyword supports a comma-separated list */
3947 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003948 sa = NULL; /* store arg */
3949 while (*nw && *nw != ',') {
3950 if (*nw == '(') {
3951 *nw = 0;
3952 sa = ++nw;
3953 while (*nw != ')') {
3954 if (!*nw) {
3955 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3956 file, linenum, args[0], cw);
3957 err_code |= ERR_ALERT | ERR_FATAL;
3958 goto out;
3959 }
3960 nw++;
3961 }
3962 *nw = '\0';
3963 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003964 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003965 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003966 if (*nw)
3967 *nw++ = '\0';
3968 type = stktable_get_data_type(cw);
3969 if (type < 0) {
3970 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3971 file, linenum, args[0], cw);
3972 err_code |= ERR_ALERT | ERR_FATAL;
3973 goto out;
3974 }
Willy Tarreauac782882010-06-20 10:41:54 +02003975
3976 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3977 switch (err) {
3978 case PE_NONE: break;
3979 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003980 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3981 file, linenum, args[0], cw);
3982 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003983 break;
3984
3985 case PE_ARG_MISSING:
3986 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3987 file, linenum, args[0], cw);
3988 err_code |= ERR_ALERT | ERR_FATAL;
3989 goto out;
3990
3991 case PE_ARG_NOT_USED:
3992 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3993 file, linenum, args[0], cw);
3994 err_code |= ERR_ALERT | ERR_FATAL;
3995 goto out;
3996
3997 default:
3998 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3999 file, linenum, args[0], cw);
4000 err_code |= ERR_ALERT | ERR_FATAL;
4001 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004002 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004003 }
4004 myidx++;
4005 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004006 else {
4007 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
4008 file, linenum, args[myidx]);
4009 err_code |= ERR_ALERT | ERR_FATAL;
4010 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004011 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004012 }
4013
4014 if (!curproxy->table.size) {
4015 Alert("parsing [%s:%d] : stick-table: missing size.\n",
4016 file, linenum);
4017 err_code |= ERR_ALERT | ERR_FATAL;
4018 goto out;
4019 }
4020
4021 if (curproxy->table.type == (unsigned int)-1) {
4022 Alert("parsing [%s:%d] : stick-table: missing type.\n",
4023 file, linenum);
4024 err_code |= ERR_ALERT | ERR_FATAL;
4025 goto out;
4026 }
4027 }
4028 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004029 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02004030 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004031 int myidx = 0;
4032 const char *name = NULL;
4033 int flags;
4034
4035 if (curproxy == &defproxy) {
4036 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4037 err_code |= ERR_ALERT | ERR_FATAL;
4038 goto out;
4039 }
4040
4041 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
4042 err_code |= ERR_WARN;
4043 goto out;
4044 }
4045
4046 myidx++;
4047 if ((strcmp(args[myidx], "store") == 0) ||
4048 (strcmp(args[myidx], "store-request") == 0)) {
4049 myidx++;
4050 flags = STK_IS_STORE;
4051 }
4052 else if (strcmp(args[myidx], "store-response") == 0) {
4053 myidx++;
4054 flags = STK_IS_STORE | STK_ON_RSP;
4055 }
4056 else if (strcmp(args[myidx], "match") == 0) {
4057 myidx++;
4058 flags = STK_IS_MATCH;
4059 }
4060 else if (strcmp(args[myidx], "on") == 0) {
4061 myidx++;
4062 flags = STK_IS_MATCH | STK_IS_STORE;
4063 }
4064 else {
4065 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
4066 err_code |= ERR_ALERT | ERR_FATAL;
4067 goto out;
4068 }
4069
4070 if (*(args[myidx]) == 0) {
4071 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
4072 err_code |= ERR_ALERT | ERR_FATAL;
4073 goto out;
4074 }
4075
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004076 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01004077 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004078 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01004079 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004080 err_code |= ERR_ALERT | ERR_FATAL;
4081 goto out;
4082 }
4083
4084 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01004085 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
4086 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
4087 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004088 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004089 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004090 goto out;
4091 }
4092 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01004093 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
4094 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
4095 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004096 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004097 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004098 goto out;
4099 }
4100 }
4101
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004102 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01004103 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004104
Emeric Brunb982a3d2010-01-04 15:45:53 +01004105 if (strcmp(args[myidx], "table") == 0) {
4106 myidx++;
4107 name = args[myidx++];
4108 }
4109
Willy Tarreauef6494c2010-01-28 17:12:36 +01004110 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004111 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
4112 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
4113 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004114 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004115 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004116 goto out;
4117 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004118 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01004119 else if (*(args[myidx])) {
4120 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
4121 file, linenum, args[0], args[myidx]);
4122 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004123 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01004124 goto out;
4125 }
Emeric Brun97679e72010-09-23 17:56:44 +02004126 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004127 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02004128 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004129 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01004130
Emeric Brunb982a3d2010-01-04 15:45:53 +01004131 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
4132 rule->cond = cond;
4133 rule->expr = expr;
4134 rule->flags = flags;
4135 rule->table.name = name ? strdup(name) : NULL;
4136 LIST_INIT(&rule->list);
4137 if (flags & STK_ON_RSP)
4138 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
4139 else
4140 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
4141 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004142 else if (!strcmp(args[0], "stats")) {
4143 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
4144 curproxy->uri_auth = NULL; /* we must detach from the default config */
4145
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004146 if (!*args[1]) {
4147 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02004148 } else if (!strcmp(args[1], "admin")) {
4149 struct stats_admin_rule *rule;
4150
4151 if (curproxy == &defproxy) {
4152 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
4153 err_code |= ERR_ALERT | ERR_FATAL;
4154 goto out;
4155 }
4156
4157 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4158 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4159 err_code |= ERR_ALERT | ERR_ABORT;
4160 goto out;
4161 }
4162
4163 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4164 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4165 file, linenum, args[0], args[1]);
4166 err_code |= ERR_ALERT | ERR_FATAL;
4167 goto out;
4168 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004169 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4170 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
4171 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02004172 err_code |= ERR_ALERT | ERR_FATAL;
4173 goto out;
4174 }
4175
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004176 err_code |= warnif_cond_conflicts(cond,
4177 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4178 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02004179
4180 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
4181 rule->cond = cond;
4182 LIST_INIT(&rule->list);
4183 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004184 } else if (!strcmp(args[1], "uri")) {
4185 if (*(args[2]) == 0) {
4186 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004187 err_code |= ERR_ALERT | ERR_FATAL;
4188 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004189 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
4190 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004191 err_code |= ERR_ALERT | ERR_ABORT;
4192 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004193 }
4194 } else if (!strcmp(args[1], "realm")) {
4195 if (*(args[2]) == 0) {
4196 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004197 err_code |= ERR_ALERT | ERR_FATAL;
4198 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004199 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
4200 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004201 err_code |= ERR_ALERT | ERR_ABORT;
4202 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004203 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02004204 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004205 unsigned interval;
4206
4207 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
4208 if (err) {
4209 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
4210 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004211 err_code |= ERR_ALERT | ERR_FATAL;
4212 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004213 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
4214 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004215 err_code |= ERR_ALERT | ERR_ABORT;
4216 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004217 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004218 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004219 struct act_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004220
4221 if (curproxy == &defproxy) {
4222 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4223 err_code |= ERR_ALERT | ERR_FATAL;
4224 goto out;
4225 }
4226
4227 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4228 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4229 err_code |= ERR_ALERT | ERR_ABORT;
4230 goto out;
4231 }
4232
Willy Tarreauff011f22011-01-06 17:51:27 +01004233 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004234 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct act_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004235 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
4236 file, linenum, args[0]);
4237 err_code |= ERR_WARN;
4238 }
4239
Willy Tarreauff011f22011-01-06 17:51:27 +01004240 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004241
Willy Tarreauff011f22011-01-06 17:51:27 +01004242 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004243 err_code |= ERR_ALERT | ERR_ABORT;
4244 goto out;
4245 }
4246
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004247 err_code |= warnif_cond_conflicts(rule->cond,
4248 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4249 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01004250 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004251
Willy Tarreaubaaee002006-06-26 02:48:02 +02004252 } else if (!strcmp(args[1], "auth")) {
4253 if (*(args[2]) == 0) {
4254 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004255 err_code |= ERR_ALERT | ERR_FATAL;
4256 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004257 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
4258 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004259 err_code |= ERR_ALERT | ERR_ABORT;
4260 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004261 }
4262 } else if (!strcmp(args[1], "scope")) {
4263 if (*(args[2]) == 0) {
4264 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004265 err_code |= ERR_ALERT | ERR_FATAL;
4266 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004267 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
4268 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004269 err_code |= ERR_ALERT | ERR_ABORT;
4270 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004271 }
4272 } else if (!strcmp(args[1], "enable")) {
4273 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4274 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004275 err_code |= ERR_ALERT | ERR_ABORT;
4276 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004277 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004278 } else if (!strcmp(args[1], "hide-version")) {
4279 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
4280 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004281 err_code |= ERR_ALERT | ERR_ABORT;
4282 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004283 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01004284 } else if (!strcmp(args[1], "show-legends")) {
4285 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
4286 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4287 err_code |= ERR_ALERT | ERR_ABORT;
4288 goto out;
4289 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004290 } else if (!strcmp(args[1], "show-node")) {
4291
4292 if (*args[2]) {
4293 int i;
4294 char c;
4295
4296 for (i=0; args[2][i]; i++) {
4297 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01004298 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
4299 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004300 break;
4301 }
4302
4303 if (!i || args[2][i]) {
4304 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
4305 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
4306 file, linenum, args[0], args[1]);
4307 err_code |= ERR_ALERT | ERR_FATAL;
4308 goto out;
4309 }
4310 }
4311
4312 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
4313 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4314 err_code |= ERR_ALERT | ERR_ABORT;
4315 goto out;
4316 }
4317 } else if (!strcmp(args[1], "show-desc")) {
4318 char *desc = NULL;
4319
4320 if (*args[2]) {
4321 int i, len=0;
4322 char *d;
4323
Willy Tarreau348acfe2014-04-14 15:00:39 +02004324 for (i = 2; *args[i]; i++)
4325 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004326
4327 desc = d = (char *)calloc(1, len);
4328
Willy Tarreau348acfe2014-04-14 15:00:39 +02004329 d += snprintf(d, desc + len - d, "%s", args[2]);
4330 for (i = 3; *args[i]; i++)
4331 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004332 }
4333
4334 if (!*args[2] && !global.desc)
4335 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
4336 file, linenum, args[1]);
4337 else {
4338 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
4339 free(desc);
4340 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4341 err_code |= ERR_ALERT | ERR_ABORT;
4342 goto out;
4343 }
4344 free(desc);
4345 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004346 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004347stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02004348 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 +01004349 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004350 err_code |= ERR_ALERT | ERR_FATAL;
4351 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004352 }
4353 }
4354 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004355 int optnum;
4356
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004357 if (*(args[1]) == '\0') {
4358 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
4359 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004360 err_code |= ERR_ALERT | ERR_FATAL;
4361 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004362 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01004363
4364 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
4365 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004366 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
4367 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4368 file, linenum, cfg_opts[optnum].name);
4369 err_code |= ERR_ALERT | ERR_FATAL;
4370 goto out;
4371 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004372 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4373 goto out;
4374
Willy Tarreau93893792009-07-23 13:19:11 +02004375 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
4376 err_code |= ERR_WARN;
4377 goto out;
4378 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004379
Willy Tarreau3842f002009-06-14 11:39:52 +02004380 curproxy->no_options &= ~cfg_opts[optnum].val;
4381 curproxy->options &= ~cfg_opts[optnum].val;
4382
4383 switch (kwm) {
4384 case KWM_STD:
4385 curproxy->options |= cfg_opts[optnum].val;
4386 break;
4387 case KWM_NO:
4388 curproxy->no_options |= cfg_opts[optnum].val;
4389 break;
4390 case KWM_DEF: /* already cleared */
4391 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004392 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004393
Willy Tarreau93893792009-07-23 13:19:11 +02004394 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004395 }
4396 }
4397
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004398 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
4399 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004400 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
4401 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4402 file, linenum, cfg_opts2[optnum].name);
4403 err_code |= ERR_ALERT | ERR_FATAL;
4404 goto out;
4405 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004406 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4407 goto out;
Willy Tarreau93893792009-07-23 13:19:11 +02004408 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4409 err_code |= ERR_WARN;
4410 goto out;
4411 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004412
Willy Tarreau3842f002009-06-14 11:39:52 +02004413 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4414 curproxy->options2 &= ~cfg_opts2[optnum].val;
4415
4416 switch (kwm) {
4417 case KWM_STD:
4418 curproxy->options2 |= cfg_opts2[optnum].val;
4419 break;
4420 case KWM_NO:
4421 curproxy->no_options2 |= cfg_opts2[optnum].val;
4422 break;
4423 case KWM_DEF: /* already cleared */
4424 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004425 }
Willy Tarreau93893792009-07-23 13:19:11 +02004426 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004427 }
4428 }
4429
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004430 /* HTTP options override each other. They can be cancelled using
4431 * "no option xxx" which only switches to default mode if the mode
4432 * was this one (useful for cancelling options set in defaults
4433 * sections).
4434 */
4435 if (strcmp(args[1], "httpclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004436 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4437 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004438 if (kwm == KWM_STD) {
4439 curproxy->options &= ~PR_O_HTTP_MODE;
4440 curproxy->options |= PR_O_HTTP_PCL;
4441 goto out;
4442 }
4443 else if (kwm == KWM_NO) {
4444 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4445 curproxy->options &= ~PR_O_HTTP_MODE;
4446 goto out;
4447 }
4448 }
4449 else if (strcmp(args[1], "forceclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004450 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4451 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004452 if (kwm == KWM_STD) {
4453 curproxy->options &= ~PR_O_HTTP_MODE;
4454 curproxy->options |= PR_O_HTTP_FCL;
4455 goto out;
4456 }
4457 else if (kwm == KWM_NO) {
4458 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4459 curproxy->options &= ~PR_O_HTTP_MODE;
4460 goto out;
4461 }
4462 }
4463 else if (strcmp(args[1], "http-server-close") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004464 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4465 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004466 if (kwm == KWM_STD) {
4467 curproxy->options &= ~PR_O_HTTP_MODE;
4468 curproxy->options |= PR_O_HTTP_SCL;
4469 goto out;
4470 }
4471 else if (kwm == KWM_NO) {
4472 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4473 curproxy->options &= ~PR_O_HTTP_MODE;
4474 goto out;
4475 }
4476 }
4477 else if (strcmp(args[1], "http-keep-alive") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004478 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4479 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004480 if (kwm == KWM_STD) {
4481 curproxy->options &= ~PR_O_HTTP_MODE;
4482 curproxy->options |= PR_O_HTTP_KAL;
4483 goto out;
4484 }
4485 else if (kwm == KWM_NO) {
4486 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4487 curproxy->options &= ~PR_O_HTTP_MODE;
4488 goto out;
4489 }
4490 }
4491 else if (strcmp(args[1], "http-tunnel") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004492 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4493 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004494 if (kwm == KWM_STD) {
4495 curproxy->options &= ~PR_O_HTTP_MODE;
4496 curproxy->options |= PR_O_HTTP_TUN;
4497 goto out;
4498 }
4499 else if (kwm == KWM_NO) {
4500 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4501 curproxy->options &= ~PR_O_HTTP_MODE;
4502 goto out;
4503 }
4504 }
4505
Joseph Lynch726ab712015-05-11 23:25:34 -07004506 /* Redispatch can take an integer argument that control when the
4507 * resispatch occurs. All values are relative to the retries option.
4508 * This can be cancelled using "no option xxx".
4509 */
4510 if (strcmp(args[1], "redispatch") == 0) {
4511 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
4512 err_code |= ERR_WARN;
4513 goto out;
4514 }
4515
4516 curproxy->no_options &= ~PR_O_REDISP;
4517 curproxy->options &= ~PR_O_REDISP;
4518
4519 switch (kwm) {
4520 case KWM_STD:
4521 curproxy->options |= PR_O_REDISP;
4522 curproxy->redispatch_after = -1;
4523 if(*args[2]) {
4524 curproxy->redispatch_after = atol(args[2]);
4525 }
4526 break;
4527 case KWM_NO:
4528 curproxy->no_options |= PR_O_REDISP;
4529 curproxy->redispatch_after = 0;
4530 break;
4531 case KWM_DEF: /* already cleared */
4532 break;
4533 }
4534 goto out;
4535 }
4536
Willy Tarreau3842f002009-06-14 11:39:52 +02004537 if (kwm != KWM_STD) {
4538 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004539 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004540 err_code |= ERR_ALERT | ERR_FATAL;
4541 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004542 }
4543
Emeric Brun3a058f32009-06-30 18:26:00 +02004544 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004545 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004546 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004547 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004548 if (*(args[2]) != '\0') {
4549 if (!strcmp(args[2], "clf")) {
4550 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004551 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004552 } else {
William Lallemand77063bc2015-05-28 18:02:48 +02004553 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004554 err_code |= ERR_ALERT | ERR_FATAL;
4555 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004556 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004557 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
4558 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004559 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004560 if (curproxy->conf.logformat_string != default_http_log_format &&
4561 curproxy->conf.logformat_string != default_tcp_log_format &&
4562 curproxy->conf.logformat_string != clf_http_log_format)
4563 free(curproxy->conf.logformat_string);
4564 curproxy->conf.logformat_string = logformat;
4565
4566 free(curproxy->conf.lfs_file);
4567 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4568 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004569 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004570 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004571 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004572 if (curproxy->conf.logformat_string != default_http_log_format &&
4573 curproxy->conf.logformat_string != default_tcp_log_format &&
4574 curproxy->conf.logformat_string != clf_http_log_format)
4575 free(curproxy->conf.logformat_string);
4576 curproxy->conf.logformat_string = default_tcp_log_format;
4577
4578 free(curproxy->conf.lfs_file);
4579 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4580 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemanddf1425a2015-04-28 20:17:49 +02004581
4582 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4583 goto out;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004584 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004585 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004586 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004587 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004588 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004589
William Lallemanddf1425a2015-04-28 20:17:49 +02004590 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4591 goto out;
4592
Willy Tarreau13943ab2006-12-31 00:24:10 +01004593 if (curproxy->cap & PR_CAP_FE)
4594 curproxy->options |= PR_O_TCP_CLI_KA;
4595 if (curproxy->cap & PR_CAP_BE)
4596 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004597 }
4598 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004599 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004600 err_code |= ERR_WARN;
4601
Willy Tarreaubaaee002006-06-26 02:48:02 +02004602 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004603 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004604 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004605 curproxy->options2 &= ~PR_O2_CHK_ANY;
4606 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004607 if (!*args[2]) { /* no argument */
4608 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4609 curproxy->check_len = strlen(DEF_CHECK_REQ);
4610 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004611 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004612 curproxy->check_req = (char *)malloc(reqlen);
4613 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004614 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004615 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004616 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004617 if (*args[4])
4618 reqlen += strlen(args[4]);
4619 else
4620 reqlen += strlen("HTTP/1.0");
4621
4622 curproxy->check_req = (char *)malloc(reqlen);
4623 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004624 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004625 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004626 if (alertif_too_many_args_idx(3, 1, file, linenum, args, &err_code))
4627 goto out;
Willy Tarreauf3c69202006-07-09 16:42:34 +02004628 }
4629 else if (!strcmp(args[1], "ssl-hello-chk")) {
4630 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004631 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004632 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004633
Willy Tarreaua534fea2008-08-03 12:19:50 +02004634 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004635 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004636 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004637 curproxy->options2 |= PR_O2_SSL3_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004638
4639 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4640 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004641 }
Willy Tarreau23677902007-05-08 23:50:35 +02004642 else if (!strcmp(args[1], "smtpchk")) {
4643 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004644 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004645 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004646 curproxy->options2 &= ~PR_O2_CHK_ANY;
4647 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004648
4649 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4650 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4651 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4652 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4653 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4654 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
4655 curproxy->check_req = (char *)malloc(reqlen);
4656 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4657 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4658 } else {
4659 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4660 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4661 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4662 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4663 }
4664 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004665 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4666 goto out;
Willy Tarreau23677902007-05-08 23:50:35 +02004667 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004668 else if (!strcmp(args[1], "pgsql-check")) {
4669 /* use PostgreSQL request to check servers' health */
4670 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4671 err_code |= ERR_WARN;
4672
4673 free(curproxy->check_req);
4674 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004675 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004676 curproxy->options2 |= PR_O2_PGSQL_CHK;
4677
4678 if (*(args[2])) {
4679 int cur_arg = 2;
4680
4681 while (*(args[cur_arg])) {
4682 if (strcmp(args[cur_arg], "user") == 0) {
4683 char * packet;
4684 uint32_t packet_len;
4685 uint32_t pv;
4686
4687 /* suboption header - needs additional argument for it */
4688 if (*(args[cur_arg+1]) == 0) {
4689 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4690 file, linenum, args[0], args[1], args[cur_arg]);
4691 err_code |= ERR_ALERT | ERR_FATAL;
4692 goto out;
4693 }
4694
4695 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4696 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4697 pv = htonl(0x30000); /* protocol version 3.0 */
4698
4699 packet = (char*) calloc(1, packet_len);
4700
4701 memcpy(packet + 4, &pv, 4);
4702
4703 /* copy "user" */
4704 memcpy(packet + 8, "user", 4);
4705
4706 /* copy username */
4707 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4708
4709 free(curproxy->check_req);
4710 curproxy->check_req = packet;
4711 curproxy->check_len = packet_len;
4712
4713 packet_len = htonl(packet_len);
4714 memcpy(packet, &packet_len, 4);
4715 cur_arg += 2;
4716 } else {
4717 /* unknown suboption - catchall */
4718 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4719 file, linenum, args[0], args[1]);
4720 err_code |= ERR_ALERT | ERR_FATAL;
4721 goto out;
4722 }
4723 } /* end while loop */
4724 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004725 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4726 goto out;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004727 }
4728
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004729 else if (!strcmp(args[1], "redis-check")) {
4730 /* use REDIS PING request to check servers' health */
4731 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4732 err_code |= ERR_WARN;
4733
4734 free(curproxy->check_req);
4735 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004736 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004737 curproxy->options2 |= PR_O2_REDIS_CHK;
4738
4739 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
4740 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4741 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004742
4743 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4744 goto out;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004745 }
4746
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004747 else if (!strcmp(args[1], "mysql-check")) {
4748 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004749 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4750 err_code |= ERR_WARN;
4751
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004752 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004753 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004754 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004755 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004756
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004757 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004758 * const char mysql40_client_auth_pkt[] = {
4759 * "\x0e\x00\x00" // packet length
4760 * "\x01" // packet number
4761 * "\x00\x00" // client capabilities
4762 * "\x00\x00\x01" // max packet
4763 * "haproxy\x00" // username (null terminated string)
4764 * "\x00" // filler (always 0x00)
4765 * "\x01\x00\x00" // packet length
4766 * "\x00" // packet number
4767 * "\x01" // COM_QUIT command
4768 * };
4769 */
4770
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004771 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4772 * const char mysql41_client_auth_pkt[] = {
4773 * "\x0e\x00\x00\" // packet length
4774 * "\x01" // packet number
4775 * "\x00\x00\x00\x00" // client capabilities
4776 * "\x00\x00\x00\x01" // max packet
4777 * "\x21" // character set (UTF-8)
4778 * char[23] // All zeroes
4779 * "haproxy\x00" // username (null terminated string)
4780 * "\x00" // filler (always 0x00)
4781 * "\x01\x00\x00" // packet length
4782 * "\x00" // packet number
4783 * "\x01" // COM_QUIT command
4784 * };
4785 */
4786
4787
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004788 if (*(args[2])) {
4789 int cur_arg = 2;
4790
4791 while (*(args[cur_arg])) {
4792 if (strcmp(args[cur_arg], "user") == 0) {
4793 char *mysqluser;
4794 int packetlen, reqlen, userlen;
4795
4796 /* suboption header - needs additional argument for it */
4797 if (*(args[cur_arg+1]) == 0) {
4798 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4799 file, linenum, args[0], args[1], args[cur_arg]);
4800 err_code |= ERR_ALERT | ERR_FATAL;
4801 goto out;
4802 }
4803 mysqluser = args[cur_arg + 1];
4804 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004805
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004806 if (*(args[cur_arg+2])) {
4807 if (!strcmp(args[cur_arg+2], "post-41")) {
4808 packetlen = userlen + 7 + 27;
4809 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004810
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004811 free(curproxy->check_req);
4812 curproxy->check_req = (char *)calloc(1, reqlen);
4813 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004814
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004815 snprintf(curproxy->check_req, 4, "%c%c%c",
4816 ((unsigned char) packetlen & 0xff),
4817 ((unsigned char) (packetlen >> 8) & 0xff),
4818 ((unsigned char) (packetlen >> 16) & 0xff));
4819
4820 curproxy->check_req[3] = 1;
4821 curproxy->check_req[5] = 130;
4822 curproxy->check_req[11] = 1;
4823 curproxy->check_req[12] = 33;
4824 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4825 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4826 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4827 cur_arg += 3;
4828 } else {
4829 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4830 err_code |= ERR_ALERT | ERR_FATAL;
4831 goto out;
4832 }
4833 } else {
4834 packetlen = userlen + 7;
4835 reqlen = packetlen + 9;
4836
4837 free(curproxy->check_req);
4838 curproxy->check_req = (char *)calloc(1, reqlen);
4839 curproxy->check_len = reqlen;
4840
4841 snprintf(curproxy->check_req, 4, "%c%c%c",
4842 ((unsigned char) packetlen & 0xff),
4843 ((unsigned char) (packetlen >> 8) & 0xff),
4844 ((unsigned char) (packetlen >> 16) & 0xff));
4845
4846 curproxy->check_req[3] = 1;
4847 curproxy->check_req[5] = 128;
4848 curproxy->check_req[8] = 1;
4849 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4850 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4851 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4852 cur_arg += 2;
4853 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004854 } else {
4855 /* unknown suboption - catchall */
4856 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4857 file, linenum, args[0], args[1]);
4858 err_code |= ERR_ALERT | ERR_FATAL;
4859 goto out;
4860 }
4861 } /* end while loop */
4862 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004863 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004864 else if (!strcmp(args[1], "ldap-check")) {
4865 /* use LDAP request to check servers' health */
4866 free(curproxy->check_req);
4867 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004868 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004869 curproxy->options2 |= PR_O2_LDAP_CHK;
4870
4871 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
4872 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
4873 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004874 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4875 goto out;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004876 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004877 else if (!strcmp(args[1], "tcp-check")) {
4878 /* use raw TCPCHK send/expect to check servers' health */
4879 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4880 err_code |= ERR_WARN;
4881
4882 free(curproxy->check_req);
4883 curproxy->check_req = NULL;
4884 curproxy->options2 &= ~PR_O2_CHK_ANY;
4885 curproxy->options2 |= PR_O2_TCPCHK_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004886 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4887 goto out;
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004888 }
Simon Horman98637e52014-06-20 12:30:16 +09004889 else if (!strcmp(args[1], "external-check")) {
4890 /* excute an external command to check servers' health */
4891 free(curproxy->check_req);
4892 curproxy->check_req = NULL;
4893 curproxy->options2 &= ~PR_O2_CHK_ANY;
4894 curproxy->options2 |= PR_O2_EXT_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004895 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4896 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09004897 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004898 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004899 int cur_arg;
4900
4901 /* insert x-forwarded-for field, but not for the IP address listed as an except.
4902 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004903 */
Ross Westaf72a1d2008-08-03 10:51:45 +02004904
Willy Tarreau87cf5142011-08-19 22:57:24 +02004905 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02004906
4907 free(curproxy->fwdfor_hdr_name);
4908 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
4909 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
4910
4911 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
4912 cur_arg = 2;
4913 while (*(args[cur_arg])) {
4914 if (!strcmp(args[cur_arg], "except")) {
4915 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004916 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004917 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4918 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004919 err_code |= ERR_ALERT | ERR_FATAL;
4920 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004921 }
4922 /* flush useless bits */
4923 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02004924 cur_arg += 2;
4925 } else if (!strcmp(args[cur_arg], "header")) {
4926 /* suboption header - needs additional argument for it */
4927 if (*(args[cur_arg+1]) == 0) {
4928 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4929 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004930 err_code |= ERR_ALERT | ERR_FATAL;
4931 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02004932 }
4933 free(curproxy->fwdfor_hdr_name);
4934 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
4935 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
4936 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02004937 } else if (!strcmp(args[cur_arg], "if-none")) {
4938 curproxy->options &= ~PR_O_FF_ALWAYS;
4939 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004940 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02004941 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02004942 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02004943 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004944 err_code |= ERR_ALERT | ERR_FATAL;
4945 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004946 }
Ross Westaf72a1d2008-08-03 10:51:45 +02004947 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004948 }
Maik Broemme2850cb42009-04-17 18:53:21 +02004949 else if (!strcmp(args[1], "originalto")) {
4950 int cur_arg;
4951
4952 /* insert x-original-to field, but not for the IP address listed as an except.
4953 * set default options (ie: bitfield, header name, etc)
4954 */
4955
4956 curproxy->options |= PR_O_ORGTO;
4957
4958 free(curproxy->orgto_hdr_name);
4959 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
4960 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
4961
Willy Tarreau87cf5142011-08-19 22:57:24 +02004962 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02004963 cur_arg = 2;
4964 while (*(args[cur_arg])) {
4965 if (!strcmp(args[cur_arg], "except")) {
4966 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004967 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 +02004968 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4969 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004970 err_code |= ERR_ALERT | ERR_FATAL;
4971 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004972 }
4973 /* flush useless bits */
4974 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
4975 cur_arg += 2;
4976 } else if (!strcmp(args[cur_arg], "header")) {
4977 /* suboption header - needs additional argument for it */
4978 if (*(args[cur_arg+1]) == 0) {
4979 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4980 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004981 err_code |= ERR_ALERT | ERR_FATAL;
4982 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004983 }
4984 free(curproxy->orgto_hdr_name);
4985 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
4986 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
4987 cur_arg += 2;
4988 } else {
4989 /* unknown suboption - catchall */
4990 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
4991 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004992 err_code |= ERR_ALERT | ERR_FATAL;
4993 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004994 }
4995 } /* end while loop */
4996 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004997 else {
4998 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004999 err_code |= ERR_ALERT | ERR_FATAL;
5000 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005001 }
Willy Tarreau93893792009-07-23 13:19:11 +02005002 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005003 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005004 else if (!strcmp(args[0], "default_backend")) {
5005 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005006 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005007
5008 if (*(args[1]) == 0) {
5009 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005010 err_code |= ERR_ALERT | ERR_FATAL;
5011 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005012 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005013 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005014 curproxy->defbe.name = strdup(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005015
5016 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5017 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005018 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005019 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01005020 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005021 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005022
Willy Tarreaua3c504c2014-04-28 22:37:32 +02005023 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
5024 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 +01005025 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005026 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005027 /* enable reconnections to dispatch */
5028 curproxy->options |= PR_O_REDISP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005029
5030 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5031 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005032 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005033 else if (!strcmp(args[0], "http-reuse")) {
5034 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5035 err_code |= ERR_WARN;
5036
5037 if (strcmp(args[1], "never") == 0) {
5038 /* enable a graceful server shutdown on an HTTP 404 response */
5039 curproxy->options &= ~PR_O_REUSE_MASK;
5040 curproxy->options |= PR_O_REUSE_NEVR;
5041 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5042 goto out;
5043 }
Willy Tarreau161d45f2015-08-05 16:02:46 +02005044 else if (strcmp(args[1], "safe") == 0) {
5045 /* enable a graceful server shutdown on an HTTP 404 response */
5046 curproxy->options &= ~PR_O_REUSE_MASK;
5047 curproxy->options |= PR_O_REUSE_SAFE;
5048 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5049 goto out;
5050 }
Willy Tarreau449d74a2015-08-05 17:16:33 +02005051 else if (strcmp(args[1], "aggressive") == 0) {
5052 curproxy->options &= ~PR_O_REUSE_MASK;
5053 curproxy->options |= PR_O_REUSE_AGGR;
5054 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5055 goto out;
5056 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005057 else if (strcmp(args[1], "always") == 0) {
5058 /* enable a graceful server shutdown on an HTTP 404 response */
5059 curproxy->options &= ~PR_O_REUSE_MASK;
5060 curproxy->options |= PR_O_REUSE_ALWS;
5061 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5062 goto out;
5063 }
5064 else {
Willy Tarreau449d74a2015-08-05 17:16:33 +02005065 Alert("parsing [%s:%d] : '%s' only supports 'never', 'safe', 'aggressive', 'always'.\n", file, linenum, args[0]);
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005066 err_code |= ERR_ALERT | ERR_FATAL;
5067 goto out;
5068 }
5069 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005070 else if (!strcmp(args[0], "http-check")) {
5071 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005072 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01005073
5074 if (strcmp(args[1], "disable-on-404") == 0) {
5075 /* enable a graceful server shutdown on an HTTP 404 response */
5076 curproxy->options |= PR_O_DISABLE404;
William Lallemanddf1425a2015-04-28 20:17:49 +02005077 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5078 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005079 }
Willy Tarreauef781042010-01-27 11:53:01 +01005080 else if (strcmp(args[1], "send-state") == 0) {
5081 /* enable emission of the apparent state of a server in HTTP checks */
5082 curproxy->options2 |= PR_O2_CHK_SNDST;
William Lallemanddf1425a2015-04-28 20:17:49 +02005083 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5084 goto out;
Willy Tarreauef781042010-01-27 11:53:01 +01005085 }
Willy Tarreaubd741542010-03-16 18:46:54 +01005086 else if (strcmp(args[1], "expect") == 0) {
5087 const char *ptr_arg;
5088 int cur_arg;
5089
5090 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5091 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5092 err_code |= ERR_ALERT | ERR_FATAL;
5093 goto out;
5094 }
5095
5096 cur_arg = 2;
5097 /* consider exclamation marks, sole or at the beginning of a word */
5098 while (*(ptr_arg = args[cur_arg])) {
5099 while (*ptr_arg == '!') {
5100 curproxy->options2 ^= PR_O2_EXP_INV;
5101 ptr_arg++;
5102 }
5103 if (*ptr_arg)
5104 break;
5105 cur_arg++;
5106 }
5107 /* now ptr_arg points to the beginning of a word past any possible
5108 * exclamation mark, and cur_arg is the argument which holds this word.
5109 */
5110 if (strcmp(ptr_arg, "status") == 0) {
5111 if (!*(args[cur_arg + 1])) {
5112 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5113 file, linenum, args[0], args[1], ptr_arg);
5114 err_code |= ERR_ALERT | ERR_FATAL;
5115 goto out;
5116 }
5117 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005118 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005119 curproxy->expect_str = strdup(args[cur_arg + 1]);
5120 }
5121 else if (strcmp(ptr_arg, "string") == 0) {
5122 if (!*(args[cur_arg + 1])) {
5123 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5124 file, linenum, args[0], args[1], ptr_arg);
5125 err_code |= ERR_ALERT | ERR_FATAL;
5126 goto out;
5127 }
5128 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005129 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005130 curproxy->expect_str = strdup(args[cur_arg + 1]);
5131 }
5132 else if (strcmp(ptr_arg, "rstatus") == 0) {
5133 if (!*(args[cur_arg + 1])) {
5134 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5135 file, linenum, args[0], args[1], ptr_arg);
5136 err_code |= ERR_ALERT | ERR_FATAL;
5137 goto out;
5138 }
5139 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005140 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005141 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005142 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005143 free(curproxy->expect_regex);
5144 curproxy->expect_regex = NULL;
5145 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005146 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005147 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5148 error = NULL;
5149 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5150 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5151 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5152 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005153 err_code |= ERR_ALERT | ERR_FATAL;
5154 goto out;
5155 }
5156 }
5157 else if (strcmp(ptr_arg, "rstring") == 0) {
5158 if (!*(args[cur_arg + 1])) {
5159 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5160 file, linenum, args[0], args[1], ptr_arg);
5161 err_code |= ERR_ALERT | ERR_FATAL;
5162 goto out;
5163 }
5164 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005165 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005166 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005167 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005168 free(curproxy->expect_regex);
5169 curproxy->expect_regex = NULL;
5170 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005171 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005172 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5173 error = NULL;
5174 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5175 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5176 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5177 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005178 err_code |= ERR_ALERT | ERR_FATAL;
5179 goto out;
5180 }
5181 }
5182 else {
5183 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
5184 file, linenum, args[0], args[1], ptr_arg);
5185 err_code |= ERR_ALERT | ERR_FATAL;
5186 goto out;
5187 }
5188 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005189 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005190 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 +02005191 err_code |= ERR_ALERT | ERR_FATAL;
5192 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005193 }
5194 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005195 else if (!strcmp(args[0], "tcp-check")) {
5196 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5197 err_code |= ERR_WARN;
5198
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005199 if (strcmp(args[1], "comment") == 0) {
5200 int cur_arg;
5201 struct tcpcheck_rule *tcpcheck;
5202
5203 cur_arg = 1;
5204 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5205 tcpcheck->action = TCPCHK_ACT_COMMENT;
5206
5207 if (!*args[cur_arg + 1]) {
5208 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5209 file, linenum, args[cur_arg]);
5210 err_code |= ERR_ALERT | ERR_FATAL;
5211 goto out;
5212 }
5213
5214 tcpcheck->comment = strdup(args[cur_arg + 1]);
5215
5216 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
William Lallemanddf1425a2015-04-28 20:17:49 +02005217 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
5218 goto out;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005219 }
5220 else if (strcmp(args[1], "connect") == 0) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005221 const char *ptr_arg;
5222 int cur_arg;
5223 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005224
5225 /* check if first rule is also a 'connect' action */
Willy Tarreau5581c272015-05-13 12:24:53 +02005226 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
5227 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
5228 tcpcheck->action == TCPCHK_ACT_COMMENT) {
5229 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
5230 }
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005231
Willy Tarreau5581c272015-05-13 12:24:53 +02005232 if (&tcpcheck->list != &curproxy->tcpcheck_rules
5233 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
5234 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
5235 file, linenum);
5236 err_code |= ERR_ALERT | ERR_FATAL;
5237 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005238 }
5239
5240 cur_arg = 2;
5241 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5242 tcpcheck->action = TCPCHK_ACT_CONNECT;
5243
5244 /* parsing each parameters to fill up the rule */
5245 while (*(ptr_arg = args[cur_arg])) {
5246 /* tcp port */
5247 if (strcmp(args[cur_arg], "port") == 0) {
5248 if ( (atol(args[cur_arg + 1]) > 65535) ||
5249 (atol(args[cur_arg + 1]) < 1) ){
5250 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
5251 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
5252 err_code |= ERR_ALERT | ERR_FATAL;
5253 goto out;
5254 }
5255 tcpcheck->port = atol(args[cur_arg + 1]);
5256 cur_arg += 2;
5257 }
5258 /* send proxy protocol */
5259 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
5260 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
5261 cur_arg++;
5262 }
5263#ifdef USE_OPENSSL
5264 else if (strcmp(args[cur_arg], "ssl") == 0) {
5265 curproxy->options |= PR_O_TCPCHK_SSL;
5266 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
5267 cur_arg++;
5268 }
5269#endif /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005270 /* comment for this tcpcheck line */
5271 else if (strcmp(args[cur_arg], "comment") == 0) {
5272 if (!*args[cur_arg + 1]) {
5273 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5274 file, linenum, args[cur_arg]);
5275 err_code |= ERR_ALERT | ERR_FATAL;
5276 goto out;
5277 }
5278 tcpcheck->comment = strdup(args[cur_arg + 1]);
5279 cur_arg += 2;
5280 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005281 else {
5282#ifdef USE_OPENSSL
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005283 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 +01005284#else /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005285 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 +01005286#endif /* USE_OPENSSL */
5287 file, linenum, args[0], args[1], args[cur_arg]);
5288 err_code |= ERR_ALERT | ERR_FATAL;
5289 goto out;
5290 }
5291
5292 }
5293
5294 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5295 }
5296 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005297 if (! *(args[2]) ) {
5298 /* SEND string expected */
5299 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
5300 file, linenum, args[0], args[1], args[2]);
5301 err_code |= ERR_ALERT | ERR_FATAL;
5302 goto out;
5303 } else {
5304 struct tcpcheck_rule *tcpcheck;
5305
5306 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5307
5308 tcpcheck->action = TCPCHK_ACT_SEND;
5309 tcpcheck->string_len = strlen(args[2]);
5310 tcpcheck->string = strdup(args[2]);
5311 tcpcheck->expect_regex = NULL;
5312
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005313 /* comment for this tcpcheck line */
5314 if (strcmp(args[3], "comment") == 0) {
5315 if (!*args[4]) {
5316 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5317 file, linenum, args[3]);
5318 err_code |= ERR_ALERT | ERR_FATAL;
5319 goto out;
5320 }
5321 tcpcheck->comment = strdup(args[4]);
5322 }
5323
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005324 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5325 }
5326 }
5327 else if (strcmp(args[1], "send-binary") == 0) {
5328 if (! *(args[2]) ) {
5329 /* SEND binary string expected */
5330 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
5331 file, linenum, args[0], args[1], args[2]);
5332 err_code |= ERR_ALERT | ERR_FATAL;
5333 goto out;
5334 } else {
5335 struct tcpcheck_rule *tcpcheck;
5336 char *err = NULL;
5337
5338 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5339
5340 tcpcheck->action = TCPCHK_ACT_SEND;
5341 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5342 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5343 file, linenum, args[0], args[1], args[2], err);
5344 err_code |= ERR_ALERT | ERR_FATAL;
5345 goto out;
5346 }
5347 tcpcheck->expect_regex = NULL;
5348
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005349 /* comment for this tcpcheck line */
5350 if (strcmp(args[3], "comment") == 0) {
5351 if (!*args[4]) {
5352 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5353 file, linenum, args[3]);
5354 err_code |= ERR_ALERT | ERR_FATAL;
5355 goto out;
5356 }
5357 tcpcheck->comment = strdup(args[4]);
5358 }
5359
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005360 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5361 }
5362 }
5363 else if (strcmp(args[1], "expect") == 0) {
5364 const char *ptr_arg;
5365 int cur_arg;
5366 int inverse = 0;
5367
5368 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5369 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5370 err_code |= ERR_ALERT | ERR_FATAL;
5371 goto out;
5372 }
5373
5374 cur_arg = 2;
5375 /* consider exclamation marks, sole or at the beginning of a word */
5376 while (*(ptr_arg = args[cur_arg])) {
5377 while (*ptr_arg == '!') {
5378 inverse = !inverse;
5379 ptr_arg++;
5380 }
5381 if (*ptr_arg)
5382 break;
5383 cur_arg++;
5384 }
5385 /* now ptr_arg points to the beginning of a word past any possible
5386 * exclamation mark, and cur_arg is the argument which holds this word.
5387 */
5388 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005389 struct tcpcheck_rule *tcpcheck;
5390 char *err = NULL;
5391
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005392 if (!*(args[cur_arg + 1])) {
5393 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
5394 file, linenum, args[0], args[1], ptr_arg);
5395 err_code |= ERR_ALERT | ERR_FATAL;
5396 goto out;
5397 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005398
5399 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5400
5401 tcpcheck->action = TCPCHK_ACT_EXPECT;
5402 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5403 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5404 file, linenum, args[0], args[1], args[2], err);
5405 err_code |= ERR_ALERT | ERR_FATAL;
5406 goto out;
5407 }
5408 tcpcheck->expect_regex = NULL;
5409 tcpcheck->inverse = inverse;
5410
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005411 /* tcpcheck comment */
5412 cur_arg += 2;
5413 if (strcmp(args[cur_arg], "comment") == 0) {
5414 if (!*args[cur_arg + 1]) {
5415 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5416 file, linenum, args[cur_arg + 1]);
5417 err_code |= ERR_ALERT | ERR_FATAL;
5418 goto out;
5419 }
5420 tcpcheck->comment = strdup(args[cur_arg + 1]);
5421 }
5422
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005423 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5424 }
5425 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005426 struct tcpcheck_rule *tcpcheck;
5427
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005428 if (!*(args[cur_arg + 1])) {
5429 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5430 file, linenum, args[0], args[1], ptr_arg);
5431 err_code |= ERR_ALERT | ERR_FATAL;
5432 goto out;
5433 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005434
5435 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5436
5437 tcpcheck->action = TCPCHK_ACT_EXPECT;
5438 tcpcheck->string_len = strlen(args[cur_arg + 1]);
5439 tcpcheck->string = strdup(args[cur_arg + 1]);
5440 tcpcheck->expect_regex = NULL;
5441 tcpcheck->inverse = inverse;
5442
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005443 /* tcpcheck comment */
5444 cur_arg += 2;
5445 if (strcmp(args[cur_arg], "comment") == 0) {
5446 if (!*args[cur_arg + 1]) {
5447 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5448 file, linenum, args[cur_arg + 1]);
5449 err_code |= ERR_ALERT | ERR_FATAL;
5450 goto out;
5451 }
5452 tcpcheck->comment = strdup(args[cur_arg + 1]);
5453 }
5454
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005455 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5456 }
5457 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005458 struct tcpcheck_rule *tcpcheck;
5459
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005460 if (!*(args[cur_arg + 1])) {
5461 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5462 file, linenum, args[0], args[1], ptr_arg);
5463 err_code |= ERR_ALERT | ERR_FATAL;
5464 goto out;
5465 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005466
5467 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5468
5469 tcpcheck->action = TCPCHK_ACT_EXPECT;
5470 tcpcheck->string_len = 0;
5471 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005472 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
5473 error = NULL;
5474 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
5475 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5476 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5477 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005478 err_code |= ERR_ALERT | ERR_FATAL;
5479 goto out;
5480 }
5481 tcpcheck->inverse = inverse;
5482
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005483 /* tcpcheck comment */
5484 cur_arg += 2;
5485 if (strcmp(args[cur_arg], "comment") == 0) {
5486 if (!*args[cur_arg + 1]) {
5487 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5488 file, linenum, args[cur_arg + 1]);
5489 err_code |= ERR_ALERT | ERR_FATAL;
5490 goto out;
5491 }
5492 tcpcheck->comment = strdup(args[cur_arg + 1]);
5493 }
5494
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005495 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5496 }
5497 else {
5498 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
5499 file, linenum, args[0], args[1], ptr_arg);
5500 err_code |= ERR_ALERT | ERR_FATAL;
5501 goto out;
5502 }
5503 }
5504 else {
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005505 Alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005506 err_code |= ERR_ALERT | ERR_FATAL;
5507 goto out;
5508 }
5509 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01005510 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02005511 if (curproxy == &defproxy) {
5512 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005513 err_code |= ERR_ALERT | ERR_FATAL;
5514 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02005515 }
5516
Willy Tarreaub80c2302007-11-30 20:51:32 +01005517 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005518 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005519
5520 if (strcmp(args[1], "fail") == 0) {
5521 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01005522 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01005523 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
5524 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005525 err_code |= ERR_ALERT | ERR_FATAL;
5526 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005527 }
5528
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005529 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
5530 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
5531 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005532 err_code |= ERR_ALERT | ERR_FATAL;
5533 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005534 }
5535 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
5536 }
5537 else {
5538 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005539 err_code |= ERR_ALERT | ERR_FATAL;
5540 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005541 }
5542 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005543#ifdef TPROXY
5544 else if (!strcmp(args[0], "transparent")) {
5545 /* enable transparent proxy connections */
5546 curproxy->options |= PR_O_TRANSP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005547 if (alertif_too_many_args(0, file, linenum, args, &err_code))
5548 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005549 }
5550#endif
5551 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005552 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005553 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005554
Willy Tarreaubaaee002006-06-26 02:48:02 +02005555 if (*(args[1]) == 0) {
5556 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005557 err_code |= ERR_ALERT | ERR_FATAL;
5558 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005559 }
5560 curproxy->maxconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005561 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5562 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005563 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005564 else if (!strcmp(args[0], "backlog")) { /* backlog */
5565 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005566 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005567
5568 if (*(args[1]) == 0) {
5569 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005570 err_code |= ERR_ALERT | ERR_FATAL;
5571 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005572 }
5573 curproxy->backlog = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005574 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5575 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005576 }
Willy Tarreau86034312006-12-29 00:10:33 +01005577 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005578 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005579 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005580
Willy Tarreau86034312006-12-29 00:10:33 +01005581 if (*(args[1]) == 0) {
5582 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005583 err_code |= ERR_ALERT | ERR_FATAL;
5584 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005585 }
5586 curproxy->fullconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005587 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5588 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005589 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005590 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
5591 if (*(args[1]) == 0) {
5592 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005593 err_code |= ERR_ALERT | ERR_FATAL;
5594 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005595 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005596 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
5597 if (err) {
5598 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
5599 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02005600 err_code |= ERR_ALERT | ERR_FATAL;
5601 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005602 }
5603 curproxy->grace = val;
William Lallemanddf1425a2015-04-28 20:17:49 +02005604 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5605 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005606 }
5607 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01005608 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005609 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005610 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005611
Willy Tarreaubaaee002006-06-26 02:48:02 +02005612 if (curproxy == &defproxy) {
5613 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005614 err_code |= ERR_ALERT | ERR_FATAL;
5615 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005616 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005617 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005618 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005619
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02005620 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005621 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005622 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005623 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005624 goto out;
5625 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005626
5627 proto = protocol_by_family(sk->ss_family);
5628 if (!proto || !proto->connect) {
5629 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5630 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005631 err_code |= ERR_ALERT | ERR_FATAL;
5632 goto out;
5633 }
5634
5635 if (port1 != port2) {
5636 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5637 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005638 err_code |= ERR_ALERT | ERR_FATAL;
5639 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005640 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005641
5642 if (!port1) {
5643 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5644 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005645 err_code |= ERR_ALERT | ERR_FATAL;
5646 goto out;
5647 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005648
William Lallemanddf1425a2015-04-28 20:17:49 +02005649 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5650 goto out;
5651
Willy Tarreaud5191e72010-02-09 20:50:45 +01005652 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005653 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005654 }
5655 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005656 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005657 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005658
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005659 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5660 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005661 err_code |= ERR_ALERT | ERR_FATAL;
5662 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005663 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005664 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005665 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005666 /**
5667 * The syntax for hash-type config element is
5668 * hash-type {map-based|consistent} [[<algo>] avalanche]
5669 *
5670 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5671 */
5672 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005673
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005674 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5675 err_code |= ERR_WARN;
5676
5677 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005678 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5679 }
5680 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005681 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5682 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005683 else if (strcmp(args[1], "avalanche") == 0) {
5684 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]);
5685 err_code |= ERR_ALERT | ERR_FATAL;
5686 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005687 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005688 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005689 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005690 err_code |= ERR_ALERT | ERR_FATAL;
5691 goto out;
5692 }
Bhaskar98634f02013-10-29 23:30:51 -04005693
5694 /* set the hash function to use */
5695 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005696 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005697 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005698
5699 /* if consistent with no argument, then avalanche modifier is also applied */
5700 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5701 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005702 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005703 /* set the hash function */
5704 if (!strcmp(args[2], "sdbm")) {
5705 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5706 }
5707 else if (!strcmp(args[2], "djb2")) {
5708 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005709 }
5710 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005711 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005712 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005713 else if (!strcmp(args[2], "crc32")) {
5714 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5715 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005716 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005717 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 -05005718 err_code |= ERR_ALERT | ERR_FATAL;
5719 goto out;
5720 }
5721
5722 /* set the hash modifier */
5723 if (!strcmp(args[3], "avalanche")) {
5724 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5725 }
5726 else if (*args[3]) {
5727 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5728 err_code |= ERR_ALERT | ERR_FATAL;
5729 goto out;
5730 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005731 }
William Lallemanda73203e2012-03-12 12:48:57 +01005732 }
William Lallemanda73203e2012-03-12 12:48:57 +01005733 else if (strcmp(args[0], "unique-id-format") == 0) {
5734 if (!*(args[1])) {
5735 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5736 err_code |= ERR_ALERT | ERR_FATAL;
5737 goto out;
5738 }
William Lallemand3203ff42012-11-11 17:30:56 +01005739 if (*(args[2])) {
5740 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5741 err_code |= ERR_ALERT | ERR_FATAL;
5742 goto out;
5743 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005744 free(curproxy->conf.uniqueid_format_string);
5745 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005746
Willy Tarreau62a61232013-04-12 18:13:46 +02005747 free(curproxy->conf.uif_file);
5748 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5749 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005750 }
William Lallemanda73203e2012-03-12 12:48:57 +01005751
5752 else if (strcmp(args[0], "unique-id-header") == 0) {
5753 if (!*(args[1])) {
5754 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5755 err_code |= ERR_ALERT | ERR_FATAL;
5756 goto out;
5757 }
5758 free(curproxy->header_unique_id);
5759 curproxy->header_unique_id = strdup(args[1]);
5760 }
5761
William Lallemand723b73a2012-02-08 16:37:49 +01005762 else if (strcmp(args[0], "log-format") == 0) {
5763 if (!*(args[1])) {
5764 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5765 err_code |= ERR_ALERT | ERR_FATAL;
5766 goto out;
5767 }
William Lallemand3203ff42012-11-11 17:30:56 +01005768 if (*(args[2])) {
5769 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5770 err_code |= ERR_ALERT | ERR_FATAL;
5771 goto out;
5772 }
Willy Tarreau196729e2012-05-31 19:30:26 +02005773
Willy Tarreau62a61232013-04-12 18:13:46 +02005774 if (curproxy->conf.logformat_string != default_http_log_format &&
5775 curproxy->conf.logformat_string != default_tcp_log_format &&
5776 curproxy->conf.logformat_string != clf_http_log_format)
5777 free(curproxy->conf.logformat_string);
5778 curproxy->conf.logformat_string = strdup(args[1]);
5779
5780 free(curproxy->conf.lfs_file);
5781 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5782 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005783
5784 /* get a chance to improve log-format error reporting by
5785 * reporting the correct line-number when possible.
5786 */
5787 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5788 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5789 file, linenum, curproxy->id);
5790 err_code |= ERR_WARN;
5791 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005792 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01005793 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
5794 if (*(args[1]) == 0) {
5795 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
5796 err_code |= ERR_ALERT | ERR_FATAL;
5797 goto out;
5798 }
5799 free(curproxy->log_tag);
5800 curproxy->log_tag = strdup(args[1]);
5801 }
William Lallemand0f99e342011-10-12 17:50:54 +02005802 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
5803 /* delete previous herited or defined syslog servers */
5804 struct logsrv *back;
5805
5806 if (*(args[1]) != 0) {
5807 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
5808 err_code |= ERR_ALERT | ERR_FATAL;
5809 goto out;
5810 }
5811
William Lallemand723b73a2012-02-08 16:37:49 +01005812 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
5813 LIST_DEL(&tmplogsrv->list);
5814 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02005815 }
5816 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005817 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02005818 struct logsrv *logsrv;
5819
Willy Tarreaubaaee002006-06-26 02:48:02 +02005820 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005821 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01005822 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02005823 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01005824 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02005825 LIST_INIT(&node->list);
5826 LIST_ADDQ(&curproxy->logsrvs, &node->list);
5827 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005828 }
5829 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005830 struct sockaddr_storage *sk;
5831 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02005832 int arg = 0;
5833 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02005834
5835 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005836
Willy Tarreau18324f52014-06-27 18:10:07 +02005837 /* just after the address, a length may be specified */
5838 if (strcmp(args[arg+2], "len") == 0) {
5839 len = atoi(args[arg+3]);
5840 if (len < 80 || len > 65535) {
5841 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
5842 file, linenum, args[arg+3]);
5843 err_code |= ERR_ALERT | ERR_FATAL;
5844 goto out;
5845 }
5846 logsrv->maxlen = len;
5847
5848 /* skip these two args */
5849 arg += 2;
5850 }
5851 else
5852 logsrv->maxlen = MAX_SYSLOG_LEN;
5853
5854 if (logsrv->maxlen > global.max_syslog_len) {
5855 global.max_syslog_len = logsrv->maxlen;
5856 logline = realloc(logline, global.max_syslog_len + 1);
5857 }
5858
William Lallemanddf1425a2015-04-28 20:17:49 +02005859 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
5860 goto out;
5861
Willy Tarreau18324f52014-06-27 18:10:07 +02005862 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005863 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005864 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005865 err_code |= ERR_ALERT | ERR_FATAL;
5866 goto out;
5867
Willy Tarreaubaaee002006-06-26 02:48:02 +02005868 }
5869
William Lallemand0f99e342011-10-12 17:50:54 +02005870 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02005871 if (*(args[arg+3])) {
5872 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005873 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005874 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005875 err_code |= ERR_ALERT | ERR_FATAL;
5876 goto out;
5877
Willy Tarreaubaaee002006-06-26 02:48:02 +02005878 }
5879 }
5880
William Lallemand0f99e342011-10-12 17:50:54 +02005881 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02005882 if (*(args[arg+4])) {
5883 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01005884 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005885 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02005886 err_code |= ERR_ALERT | ERR_FATAL;
5887 goto out;
5888
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005889 }
5890 }
5891
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02005892 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005893 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005894 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005895 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005896 goto out;
5897 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005898
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005899 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005900
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005901 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005902 if (port1 != port2) {
5903 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5904 file, linenum, args[0], args[1]);
5905 err_code |= ERR_ALERT | ERR_FATAL;
5906 goto out;
5907 }
5908
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005909 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02005910 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005911 }
William Lallemand0f99e342011-10-12 17:50:54 +02005912
5913 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005914 }
5915 else {
5916 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
5917 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005918 err_code |= ERR_ALERT | ERR_FATAL;
5919 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005920 }
5921 }
5922 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005923 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005924 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01005925 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005926 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005927
Willy Tarreau977b8e42006-12-29 14:19:17 +01005928 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005929 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005930
Willy Tarreaubaaee002006-06-26 02:48:02 +02005931 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005932 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
5933 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005934 err_code |= ERR_ALERT | ERR_FATAL;
5935 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005936 }
Willy Tarreau368480c2009-03-01 08:27:21 +01005937
5938 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01005939 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5940 free(curproxy->conn_src.iface_name);
5941 curproxy->conn_src.iface_name = NULL;
5942 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01005943
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02005944 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005945 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005946 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005947 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005948 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005949 goto out;
5950 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005951
5952 proto = protocol_by_family(sk->ss_family);
5953 if (!proto || !proto->connect) {
5954 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005955 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005956 err_code |= ERR_ALERT | ERR_FATAL;
5957 goto out;
5958 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005959
5960 if (port1 != port2) {
5961 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5962 file, linenum, args[0], args[1]);
5963 err_code |= ERR_ALERT | ERR_FATAL;
5964 goto out;
5965 }
5966
Willy Tarreauef9a3602012-12-08 22:29:20 +01005967 curproxy->conn_src.source_addr = *sk;
5968 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005969
5970 cur_arg = 2;
5971 while (*(args[cur_arg])) {
5972 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau29fbe512015-08-20 19:35:14 +02005973#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005974 if (!*args[cur_arg + 1]) {
5975 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5976 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005977 err_code |= ERR_ALERT | ERR_FATAL;
5978 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005979 }
5980
5981 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005982 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5983 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005984 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005985 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5986 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005987 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5988 char *name, *end;
5989
5990 name = args[cur_arg+1] + 7;
5991 while (isspace(*name))
5992 name++;
5993
5994 end = name;
5995 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5996 end++;
5997
Willy Tarreauef9a3602012-12-08 22:29:20 +01005998 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5999 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
6000 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
6001 curproxy->conn_src.bind_hdr_len = end - name;
6002 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
6003 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
6004 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02006005
6006 /* now look for an occurrence number */
6007 while (isspace(*end))
6008 end++;
6009 if (*end == ',') {
6010 end++;
6011 name = end;
6012 if (*end == '-')
6013 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01006014 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02006015 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01006016 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006017 }
6018
Willy Tarreauef9a3602012-12-08 22:29:20 +01006019 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02006020 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
6021 " occurrences values smaller than %d.\n",
6022 file, linenum, MAX_HDR_HISTORY);
6023 err_code |= ERR_ALERT | ERR_FATAL;
6024 goto out;
6025 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006026 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01006027 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006028
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006029 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006030 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006031 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006032 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006033 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006034 goto out;
6035 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006036
6037 proto = protocol_by_family(sk->ss_family);
6038 if (!proto || !proto->connect) {
6039 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
6040 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006041 err_code |= ERR_ALERT | ERR_FATAL;
6042 goto out;
6043 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006044
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006045 if (port1 != port2) {
6046 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6047 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006048 err_code |= ERR_ALERT | ERR_FATAL;
6049 goto out;
6050 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006051 curproxy->conn_src.tproxy_addr = *sk;
6052 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006053 }
6054 global.last_checks |= LSTCHK_NETADM;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006055#else /* no TPROXY support */
6056 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01006057 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006058 err_code |= ERR_ALERT | ERR_FATAL;
6059 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006060#endif
6061 cur_arg += 2;
6062 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01006063 }
6064
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006065 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
6066#ifdef SO_BINDTODEVICE
6067 if (!*args[cur_arg + 1]) {
6068 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
6069 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006070 err_code |= ERR_ALERT | ERR_FATAL;
6071 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006072 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006073 free(curproxy->conn_src.iface_name);
6074 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
6075 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006076 global.last_checks |= LSTCHK_NETADM;
6077#else
6078 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
6079 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02006080 err_code |= ERR_ALERT | ERR_FATAL;
6081 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01006082#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006083 cur_arg += 2;
6084 continue;
6085 }
6086 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02006087 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006088 err_code |= ERR_ALERT | ERR_FATAL;
6089 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006090 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006091 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006092 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
6093 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
6094 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02006095 err_code |= ERR_ALERT | ERR_FATAL;
6096 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006097 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006098 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006099 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006100 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6101 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006102 err_code |= ERR_ALERT | ERR_FATAL;
6103 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006104 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006105
6106 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006107 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006108 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006109 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006110 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006111 }
6112 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006113 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006114 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006115 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006116 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006117 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006118 }
6119 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006120 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006121 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006122 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006123 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006124 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006125 }
6126 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006127 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006128 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006129 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006130 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006131 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006132 }
6133 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006134 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006135 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006136 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006137 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006138 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006139 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006140 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006141 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006142 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006143 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006144 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006145 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006146 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006147 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006148 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006149 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6150 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006151 err_code |= ERR_ALERT | ERR_FATAL;
6152 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006153 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006154
6155 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006156 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006157 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006158 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006159 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006160 }
6161 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006162 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006163 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006164 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006165 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006166 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006167 }
6168 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006169 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006170 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006171 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006172 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006173 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006174 }
6175 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006176 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006177 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006178 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006179 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006180 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006181 }
6182 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006183 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006184 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006185 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006186 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006187 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006188 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006189 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006190 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006191 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006192 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006193 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006194 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006195 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006196 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006197 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006198
Willy Tarreaubaaee002006-06-26 02:48:02 +02006199 if (curproxy == &defproxy) {
6200 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006201 err_code |= ERR_ALERT | ERR_FATAL;
6202 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006203 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006204 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006205 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006206
Willy Tarreaubaaee002006-06-26 02:48:02 +02006207 if (*(args[1]) == 0) {
6208 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006209 err_code |= ERR_ALERT | ERR_FATAL;
6210 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006211 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006212
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006213 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006214 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6215 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6216 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006217 err_code |= ERR_ALERT | ERR_FATAL;
6218 goto out;
6219 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006220 err_code |= warnif_cond_conflicts(cond,
6221 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6222 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006223 }
6224 else if (*args[2]) {
6225 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6226 file, linenum, args[0], args[2]);
6227 err_code |= ERR_ALERT | ERR_FATAL;
6228 goto out;
6229 }
6230
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006231 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006232 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006233 wl->s = strdup(args[1]);
6234 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02006235 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006236 }
6237 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006238 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006239 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6240 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006241 err_code |= ERR_ALERT | ERR_FATAL;
6242 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006243 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006244
Willy Tarreauade5ec42010-01-28 19:33:49 +01006245 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006246 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006247 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006248 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006249 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006250 }
6251 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006252 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006253 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006254 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006255 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006256 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006257 }
6258 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006259 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006260 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006261 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006262 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006263 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006264 }
6265 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006266 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006267 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6268 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006269 err_code |= ERR_ALERT | ERR_FATAL;
6270 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006271 }
6272
Willy Tarreauade5ec42010-01-28 19:33:49 +01006273 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006274 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006275 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006276 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006277 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006278 }
6279 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006280 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006281 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006282 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006283 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006284 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006285 }
6286 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006287 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006288 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006289 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006290 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006291 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006292 }
6293 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006294 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006295
Willy Tarreaubaaee002006-06-26 02:48:02 +02006296 if (curproxy == &defproxy) {
6297 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006298 err_code |= ERR_ALERT | ERR_FATAL;
6299 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006300 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006301 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006302 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006303
Willy Tarreaubaaee002006-06-26 02:48:02 +02006304 if (*(args[1]) == 0) {
6305 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006306 err_code |= ERR_ALERT | ERR_FATAL;
6307 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006308 }
6309
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006310 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006311 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6312 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6313 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006314 err_code |= ERR_ALERT | ERR_FATAL;
6315 goto out;
6316 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006317 err_code |= warnif_cond_conflicts(cond,
6318 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
6319 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006320 }
6321 else if (*args[2]) {
6322 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6323 file, linenum, args[0], args[2]);
6324 err_code |= ERR_ALERT | ERR_FATAL;
6325 goto out;
6326 }
6327
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006328 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006329 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006330 wl->s = strdup(args[1]);
6331 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006332 }
6333 else if (!strcmp(args[0], "errorloc") ||
6334 !strcmp(args[0], "errorloc302") ||
6335 !strcmp(args[0], "errorloc303")) { /* error location */
6336 int errnum, errlen;
6337 char *err;
6338
Willy Tarreau977b8e42006-12-29 14:19:17 +01006339 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006340 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006341
Willy Tarreaubaaee002006-06-26 02:48:02 +02006342 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006343 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006344 err_code |= ERR_ALERT | ERR_FATAL;
6345 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006346 }
6347
6348 errnum = atol(args[1]);
6349 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006350 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
6351 err = malloc(errlen);
6352 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006353 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006354 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
6355 err = malloc(errlen);
6356 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006357 }
6358
Willy Tarreau0f772532006-12-23 20:51:41 +01006359 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6360 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006361 chunk_destroy(&curproxy->errmsg[rc]);
6362 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01006363 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006364 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006365 }
Willy Tarreau0f772532006-12-23 20:51:41 +01006366
6367 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006368 Warning("parsing [%s:%d] : status code %d not handled by '%s', error relocation will be ignored.\n",
6369 file, linenum, errnum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006370 free(err);
6371 }
6372 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02006373 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
6374 int errnum, errlen, fd;
6375 char *err;
6376 struct stat stat;
6377
6378 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006379 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006380
6381 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006382 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006383 err_code |= ERR_ALERT | ERR_FATAL;
6384 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006385 }
6386
6387 fd = open(args[2], O_RDONLY);
6388 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
6389 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
6390 file, linenum, args[2], args[1]);
6391 if (fd >= 0)
6392 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02006393 err_code |= ERR_ALERT | ERR_FATAL;
6394 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006395 }
6396
Willy Tarreau27a674e2009-08-17 07:23:33 +02006397 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02006398 errlen = stat.st_size;
6399 } else {
6400 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02006401 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02006402 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02006403 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006404 }
6405
6406 err = malloc(errlen); /* malloc() must succeed during parsing */
6407 errnum = read(fd, err, errlen);
6408 if (errnum != errlen) {
6409 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
6410 file, linenum, args[2], args[1]);
6411 close(fd);
6412 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02006413 err_code |= ERR_ALERT | ERR_FATAL;
6414 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006415 }
6416 close(fd);
6417
6418 errnum = atol(args[1]);
6419 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6420 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006421 chunk_destroy(&curproxy->errmsg[rc]);
6422 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02006423 break;
6424 }
6425 }
6426
6427 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006428 Warning("parsing [%s:%d] : status code %d not handled by '%s', error customization will be ignored.\n",
6429 file, linenum, errnum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006430 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006431 free(err);
6432 }
6433 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006434 else if (!strcmp(args[0], "compression")) {
6435 struct comp *comp;
6436 if (curproxy->comp == NULL) {
6437 comp = calloc(1, sizeof(struct comp));
6438 curproxy->comp = comp;
6439 } else {
6440 comp = curproxy->comp;
6441 }
6442
6443 if (!strcmp(args[1], "algo")) {
6444 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01006445 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01006446
William Lallemand82fe75c2012-10-23 10:25:10 +02006447 cur_arg = 2;
6448 if (!*args[cur_arg]) {
6449 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
6450 file, linenum, args[0]);
6451 err_code |= ERR_ALERT | ERR_FATAL;
6452 goto out;
6453 }
6454 while (*(args[cur_arg])) {
6455 if (comp_append_algo(comp, args[cur_arg]) < 0) {
6456 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
6457 file, linenum, args[0], args[cur_arg]);
6458 err_code |= ERR_ALERT | ERR_FATAL;
6459 goto out;
6460 }
William Lallemand552df672012-11-07 13:21:47 +01006461 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
6462 curproxy->comp->algos->end(&ctx);
6463 } else {
6464 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
6465 file, linenum, args[0], args[cur_arg]);
6466 err_code |= ERR_ALERT | ERR_FATAL;
6467 goto out;
6468 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006469 cur_arg ++;
6470 continue;
6471 }
6472 }
Willy Tarreau70737d12012-10-27 00:34:28 +02006473 else if (!strcmp(args[1], "offload")) {
6474 comp->offload = 1;
6475 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006476 else if (!strcmp(args[1], "type")) {
6477 int cur_arg;
6478 cur_arg = 2;
6479 if (!*args[cur_arg]) {
6480 Alert("parsing [%s:%d] : '%s' expects <type>\n",
6481 file, linenum, args[0]);
6482 err_code |= ERR_ALERT | ERR_FATAL;
6483 goto out;
6484 }
6485 while (*(args[cur_arg])) {
6486 comp_append_type(comp, args[cur_arg]);
6487 cur_arg ++;
6488 continue;
6489 }
6490 }
6491 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02006492 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02006493 file, linenum, args[0]);
6494 err_code |= ERR_ALERT | ERR_FATAL;
6495 goto out;
6496 }
6497 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006498 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006499 struct cfg_kw_list *kwl;
6500 int index;
6501
6502 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6503 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6504 if (kwl->kw[index].section != CFG_LISTEN)
6505 continue;
6506 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6507 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006508 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006509 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006510 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006511 err_code |= ERR_ALERT | ERR_FATAL;
6512 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006513 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006514 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006515 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006516 err_code |= ERR_WARN;
6517 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006518 }
Willy Tarreau93893792009-07-23 13:19:11 +02006519 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006520 }
6521 }
6522 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006523
Willy Tarreau6daf3432008-01-22 16:44:08 +01006524 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006525 err_code |= ERR_ALERT | ERR_FATAL;
6526 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006527 }
Willy Tarreau93893792009-07-23 13:19:11 +02006528 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006529 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006530 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006531}
6532
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006533int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006534cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
6535{
6536#ifdef CONFIG_HAP_NS
6537 const char *err;
6538 const char *item = args[0];
6539
6540 if (!strcmp(item, "namespace_list")) {
6541 return 0;
6542 }
6543 else if (!strcmp(item, "namespace")) {
6544 size_t idx = 1;
6545 const char *current;
6546 while (*(current = args[idx++])) {
6547 err = invalid_char(current);
6548 if (err) {
6549 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6550 file, linenum, *err, item, current);
6551 return ERR_ALERT | ERR_FATAL;
6552 }
6553
6554 if (netns_store_lookup(current, strlen(current))) {
6555 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
6556 file, linenum, current);
6557 return ERR_ALERT | ERR_FATAL;
6558 }
6559 if (!netns_store_insert(current)) {
6560 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
6561 file, linenum, current);
6562 return ERR_ALERT | ERR_FATAL;
6563 }
6564 }
6565 }
6566
6567 return 0;
6568#else
6569 Alert("parsing [%s:%d]: namespace support is not compiled in.",
6570 file, linenum);
6571 return ERR_ALERT | ERR_FATAL;
6572#endif
6573}
6574
6575int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006576cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6577{
6578
6579 int err_code = 0;
6580 const char *err;
6581
6582 if (!strcmp(args[0], "userlist")) { /* new userlist */
6583 struct userlist *newul;
6584
6585 if (!*args[1]) {
6586 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6587 file, linenum, args[0]);
6588 err_code |= ERR_ALERT | ERR_FATAL;
6589 goto out;
6590 }
William Lallemand6e62fb62015-04-28 16:55:23 +02006591 if (alertif_too_many_args(1, file, linenum, args, &err_code))
6592 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006593
6594 err = invalid_char(args[1]);
6595 if (err) {
6596 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6597 file, linenum, *err, args[0], args[1]);
6598 err_code |= ERR_ALERT | ERR_FATAL;
6599 goto out;
6600 }
6601
6602 for (newul = userlist; newul; newul = newul->next)
6603 if (!strcmp(newul->name, args[1])) {
6604 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6605 file, linenum, args[1]);
6606 err_code |= ERR_WARN;
6607 goto out;
6608 }
6609
6610 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
6611 if (!newul) {
6612 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6613 err_code |= ERR_ALERT | ERR_ABORT;
6614 goto out;
6615 }
6616
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006617 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006618 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006619 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6620 err_code |= ERR_ALERT | ERR_ABORT;
6621 goto out;
6622 }
6623
6624 newul->next = userlist;
6625 userlist = newul;
6626
6627 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006628 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006629 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006630 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006631
6632 if (!*args[1]) {
6633 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6634 file, linenum, args[0]);
6635 err_code |= ERR_ALERT | ERR_FATAL;
6636 goto out;
6637 }
6638
6639 err = invalid_char(args[1]);
6640 if (err) {
6641 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6642 file, linenum, *err, args[0], args[1]);
6643 err_code |= ERR_ALERT | ERR_FATAL;
6644 goto out;
6645 }
6646
William Lallemand4ac9f542015-05-28 18:03:51 +02006647 if (!userlist)
6648 goto out;
6649
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006650 for (ag = userlist->groups; ag; ag = ag->next)
6651 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006652 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6653 file, linenum, args[1], userlist->name);
6654 err_code |= ERR_ALERT;
6655 goto out;
6656 }
6657
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006658 ag = calloc(1, sizeof(*ag));
6659 if (!ag) {
6660 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6661 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006662 goto out;
6663 }
6664
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006665 ag->name = strdup(args[1]);
6666 if (!ag) {
6667 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6668 err_code |= ERR_ALERT | ERR_ABORT;
6669 goto out;
6670 }
6671
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006672 cur_arg = 2;
6673
6674 while (*args[cur_arg]) {
6675 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006676 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006677 cur_arg += 2;
6678 continue;
6679 } else {
6680 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6681 file, linenum, args[0]);
6682 err_code |= ERR_ALERT | ERR_FATAL;
6683 goto out;
6684 }
6685 }
6686
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006687 ag->next = userlist->groups;
6688 userlist->groups = ag;
6689
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006690 } else if (!strcmp(args[0], "user")) { /* new user */
6691 struct auth_users *newuser;
6692 int cur_arg;
6693
6694 if (!*args[1]) {
6695 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6696 file, linenum, args[0]);
6697 err_code |= ERR_ALERT | ERR_FATAL;
6698 goto out;
6699 }
William Lallemand4ac9f542015-05-28 18:03:51 +02006700 if (!userlist)
6701 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006702
6703 for (newuser = userlist->users; newuser; newuser = newuser->next)
6704 if (!strcmp(newuser->user, args[1])) {
6705 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6706 file, linenum, args[1], userlist->name);
6707 err_code |= ERR_ALERT;
6708 goto out;
6709 }
6710
6711 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
6712 if (!newuser) {
6713 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6714 err_code |= ERR_ALERT | ERR_ABORT;
6715 goto out;
6716 }
6717
6718 newuser->user = strdup(args[1]);
6719
6720 newuser->next = userlist->users;
6721 userlist->users = newuser;
6722
6723 cur_arg = 2;
6724
6725 while (*args[cur_arg]) {
6726 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006727#ifdef CONFIG_HAP_CRYPT
6728 if (!crypt("", args[cur_arg + 1])) {
6729 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6730 file, linenum, newuser->user);
6731 err_code |= ERR_ALERT | ERR_FATAL;
6732 goto out;
6733 }
6734#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006735 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6736 file, linenum);
6737 err_code |= ERR_ALERT;
6738#endif
6739 newuser->pass = strdup(args[cur_arg + 1]);
6740 cur_arg += 2;
6741 continue;
6742 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6743 newuser->pass = strdup(args[cur_arg + 1]);
6744 newuser->flags |= AU_O_INSECURE;
6745 cur_arg += 2;
6746 continue;
6747 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006748 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006749 cur_arg += 2;
6750 continue;
6751 } else {
6752 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6753 file, linenum, args[0]);
6754 err_code |= ERR_ALERT | ERR_FATAL;
6755 goto out;
6756 }
6757 }
6758 } else {
6759 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6760 err_code |= ERR_ALERT | ERR_FATAL;
6761 }
6762
6763out:
6764 return err_code;
6765}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006766
6767/*
6768 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006769 * Returns the error code, 0 if OK, or any combination of :
6770 * - ERR_ABORT: must abort ASAP
6771 * - ERR_FATAL: we can continue parsing but not start the service
6772 * - ERR_WARN: a warning has been emitted
6773 * - ERR_ALERT: an alert has been emitted
6774 * Only the two first ones can stop processing, the two others are just
6775 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006776 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006777int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006778{
William Lallemand64e84512015-05-12 14:25:37 +02006779 char *thisline;
6780 int linesize = LINESIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006781 FILE *f;
6782 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02006783 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006784 struct cfg_section *cs = NULL;
6785 struct cfg_section *ics;
William Lallemand64e84512015-05-12 14:25:37 +02006786 int readbytes = 0;
6787
6788 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
William Lallemandb2f07452015-05-12 14:27:13 +02006789 Alert("parsing [%s] : out of memory.\n", file);
William Lallemand64e84512015-05-12 14:25:37 +02006790 return -1;
6791 }
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006792
6793 /* Register internal sections */
6794 if (!cfg_register_section("listen", cfg_parse_listen) ||
6795 !cfg_register_section("frontend", cfg_parse_listen) ||
6796 !cfg_register_section("backend", cfg_parse_listen) ||
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006797 !cfg_register_section("defaults", cfg_parse_listen) ||
6798 !cfg_register_section("global", cfg_parse_global) ||
6799 !cfg_register_section("userlist", cfg_parse_users) ||
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006800 !cfg_register_section("peers", cfg_parse_peers) ||
Simon Horman0d16a402015-01-30 11:22:58 +09006801 !cfg_register_section("mailers", cfg_parse_mailers) ||
Baptiste Assmann325137d2015-04-13 23:40:55 +02006802 !cfg_register_section("namespace_list", cfg_parse_netns) ||
6803 !cfg_register_section("resolvers", cfg_parse_resolvers))
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006804 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006805
Willy Tarreaubaaee002006-06-26 02:48:02 +02006806 if ((f=fopen(file,"r")) == NULL)
6807 return -1;
6808
William Lallemandb2f07452015-05-12 14:27:13 +02006809next_line:
William Lallemand64e84512015-05-12 14:25:37 +02006810 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02006811 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006812 char *end;
6813 char *args[MAX_LINE_ARGS + 1];
6814 char *line = thisline;
William Lallemandf9873ba2015-05-05 17:37:14 +02006815 int dquote = 0; /* double quote */
6816 int squote = 0; /* simple quote */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006817
Willy Tarreaubaaee002006-06-26 02:48:02 +02006818 linenum++;
6819
6820 end = line + strlen(line);
6821
William Lallemand64e84512015-05-12 14:25:37 +02006822 if (end-line == linesize-1 && *(end-1) != '\n') {
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006823 /* Check if we reached the limit and the last char is not \n.
6824 * Watch out for the last line without the terminating '\n'!
6825 */
William Lallemand64e84512015-05-12 14:25:37 +02006826 char *newline;
6827 int newlinesize = linesize * 2;
6828
6829 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
6830 if (newline == NULL) {
6831 Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
6832 file, linenum);
6833 err_code |= ERR_ALERT | ERR_FATAL;
6834 continue;
6835 }
6836
6837 readbytes = linesize - 1;
6838 linesize = newlinesize;
6839 thisline = newline;
6840 continue;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006841 }
6842
William Lallemand64e84512015-05-12 14:25:37 +02006843 readbytes = 0;
6844
Willy Tarreaubaaee002006-06-26 02:48:02 +02006845 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006846 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006847 line++;
William Lallemandf9873ba2015-05-05 17:37:14 +02006848
Willy Tarreaubaaee002006-06-26 02:48:02 +02006849 arg = 0;
6850 args[arg] = line;
6851
6852 while (*line && arg < MAX_LINE_ARGS) {
William Lallemandf9873ba2015-05-05 17:37:14 +02006853 if (*line == '"' && !squote) { /* double quote outside single quotes */
6854 if (dquote)
6855 dquote = 0;
6856 else
6857 dquote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02006858 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02006859 end--;
6860 }
6861 else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
6862 if (squote)
6863 squote = 0;
6864 else
6865 squote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02006866 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02006867 end--;
6868 }
6869 else if (*line == '\\' && !squote) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006870 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
6871 * C equivalent value. Other combinations left unchanged (eg: \1).
6872 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006873 int skip = 0;
6874 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
6875 *line = line[1];
6876 skip = 1;
6877 }
6878 else if (line[1] == 'r') {
6879 *line = '\r';
6880 skip = 1;
William Lallemandf9873ba2015-05-05 17:37:14 +02006881 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006882 else if (line[1] == 'n') {
6883 *line = '\n';
6884 skip = 1;
6885 }
6886 else if (line[1] == 't') {
6887 *line = '\t';
6888 skip = 1;
6889 }
6890 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01006891 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006892 unsigned char hex1, hex2;
6893 hex1 = toupper(line[2]) - '0';
6894 hex2 = toupper(line[3]) - '0';
6895 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
6896 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
6897 *line = (hex1<<4) + hex2;
6898 skip = 3;
6899 }
6900 else {
6901 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006902 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006903 }
William Lallemandf9873ba2015-05-05 17:37:14 +02006904 } else if (line[1] == '"') {
6905 *line = '"';
6906 skip = 1;
6907 } else if (line[1] == '\'') {
6908 *line = '\'';
6909 skip = 1;
William Lallemandb2f07452015-05-12 14:27:13 +02006910 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
6911 *line = '$';
6912 skip = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006913 }
6914 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01006915 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006916 end -= skip;
6917 }
6918 line++;
6919 }
William Lallemandf9873ba2015-05-05 17:37:14 +02006920 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006921 /* end of string, end of loop */
6922 *line = 0;
6923 break;
6924 }
William Lallemandf9873ba2015-05-05 17:37:14 +02006925 else if (!squote && !dquote && isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006926 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006927 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006928 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006929 line++;
6930 args[++arg] = line;
6931 }
William Lallemandb2f07452015-05-12 14:27:13 +02006932 else if (dquote && *line == '$') {
6933 /* environment variables are evaluated inside double quotes */
6934 char *var_beg;
6935 char *var_end;
6936 char save_char;
6937 char *value;
6938 int val_len;
6939 int newlinesize;
6940 int braces = 0;
6941
6942 var_beg = line + 1;
6943 var_end = var_beg;
6944
6945 if (*var_beg == '{') {
6946 var_beg++;
6947 var_end++;
6948 braces = 1;
6949 }
6950
6951 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
6952 Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
6953 err_code |= ERR_ALERT | ERR_FATAL;
6954 goto next_line; /* skip current line */
6955 }
6956
6957 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
6958 var_end++;
6959
6960 save_char = *var_end;
6961 *var_end = '\0';
6962 value = getenv(var_beg);
6963 *var_end = save_char;
6964 val_len = value ? strlen(value) : 0;
6965
6966 if (braces) {
6967 if (*var_end == '}') {
6968 var_end++;
6969 braces = 0;
6970 } else {
6971 Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
6972 err_code |= ERR_ALERT | ERR_FATAL;
6973 goto next_line; /* skip current line */
6974 }
6975 }
6976
6977 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
6978
6979 /* if not enough space in thisline */
6980 if (newlinesize > linesize) {
6981 char *newline;
6982
6983 newline = realloc(thisline, newlinesize * sizeof(*thisline));
6984 if (newline == NULL) {
6985 Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
6986 err_code |= ERR_ALERT | ERR_FATAL;
6987 goto next_line; /* slip current line */
6988 }
6989 /* recompute pointers if realloc returns a new pointer */
6990 if (newline != thisline) {
6991 int i;
6992 int diff;
6993
6994 for (i = 0; i <= arg; i++) {
6995 diff = args[i] - thisline;
6996 args[i] = newline + diff;
6997 }
6998
6999 diff = var_end - thisline;
7000 var_end = newline + diff;
7001 diff = end - thisline;
7002 end = newline + diff;
7003 diff = line - thisline;
7004 line = newline + diff;
7005 thisline = newline;
7006 }
7007 linesize = newlinesize;
7008 }
7009
7010 /* insert value inside the line */
7011 memmove(line + val_len, var_end, end - var_end + 1);
7012 memcpy(line, value, val_len);
7013 end += val_len - (var_end - line);
7014 line += val_len;
7015 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007016 else {
7017 line++;
7018 }
7019 }
William Lallemandb2f07452015-05-12 14:27:13 +02007020
William Lallemandf9873ba2015-05-05 17:37:14 +02007021 if (dquote) {
7022 Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
7023 err_code |= ERR_ALERT | ERR_FATAL;
7024 }
7025
7026 if (squote) {
7027 Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
7028 err_code |= ERR_ALERT | ERR_FATAL;
7029 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007030
7031 /* empty line */
7032 if (!**args)
7033 continue;
7034
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007035 if (*line) {
7036 /* we had to stop due to too many args.
7037 * Let's terminate the string, print the offending part then cut the
7038 * last arg.
7039 */
7040 while (*line && *line != '#' && *line != '\n' && *line != '\r')
7041 line++;
7042 *line = '\0';
7043
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01007044 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01007045 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007046 err_code |= ERR_ALERT | ERR_FATAL;
7047 args[arg] = line;
7048 }
7049
Willy Tarreau540abe42007-05-02 20:50:16 +02007050 /* zero out remaining args and ensure that at least one entry
7051 * is zeroed out.
7052 */
7053 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007054 args[arg] = line;
7055 }
7056
Willy Tarreau3842f002009-06-14 11:39:52 +02007057 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007058 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02007059 char *tmp;
7060
Willy Tarreau3842f002009-06-14 11:39:52 +02007061 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02007062 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007063 for (arg=0; *args[arg+1]; arg++)
7064 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02007065 *tmp = '\0'; // fix the next arg to \0
7066 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007067 }
Willy Tarreau3842f002009-06-14 11:39:52 +02007068 else if (!strcmp(args[0], "default")) {
7069 kwm = KWM_DEF;
7070 for (arg=0; *args[arg+1]; arg++)
7071 args[arg] = args[arg+1]; // shift args after inversion
7072 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007073
William Lallemand0f99e342011-10-12 17:50:54 +02007074 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
7075 strcmp(args[0], "log") != 0) {
7076 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02007077 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007078 }
7079
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007080 /* detect section start */
7081 list_for_each_entry(ics, &sections, list) {
7082 if (strcmp(args[0], ics->section_name) == 0) {
7083 cursection = ics->section_name;
7084 cs = ics;
7085 break;
7086 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007087 }
7088
Willy Tarreaubaaee002006-06-26 02:48:02 +02007089 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007090 if (cs)
7091 err_code |= cs->section_parser(file, linenum, args, kwm);
7092 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007093 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007094 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007095 }
Willy Tarreau058e9072009-07-20 09:30:05 +02007096
7097 if (err_code & ERR_ABORT)
7098 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007099 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01007100 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02007101 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007102 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02007103 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007104}
7105
Willy Tarreau64ab6072014-09-16 12:17:36 +02007106/* This function propagates processes from frontend <from> to backend <to> so
7107 * that it is always guaranteed that a backend pointed to by a frontend is
7108 * bound to all of its processes. After that, if the target is a "listen"
7109 * instance, the function recursively descends the target's own targets along
Willy Tarreau98d04852015-05-26 12:18:29 +02007110 * default_backend and use_backend rules. Since the bits are
Willy Tarreau64ab6072014-09-16 12:17:36 +02007111 * checked first to ensure that <to> is already bound to all processes of
7112 * <from>, there is no risk of looping and we ensure to follow the shortest
7113 * path to the destination.
7114 *
7115 * It is possible to set <to> to NULL for the first call so that the function
7116 * takes care of visiting the initial frontend in <from>.
7117 *
7118 * It is important to note that the function relies on the fact that all names
7119 * have already been resolved.
7120 */
7121void propagate_processes(struct proxy *from, struct proxy *to)
7122{
7123 struct switching_rule *rule;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007124
7125 if (to) {
7126 /* check whether we need to go down */
7127 if (from->bind_proc &&
7128 (from->bind_proc & to->bind_proc) == from->bind_proc)
7129 return;
7130
7131 if (!from->bind_proc && !to->bind_proc)
7132 return;
7133
7134 to->bind_proc = from->bind_proc ?
7135 (to->bind_proc | from->bind_proc) : 0;
7136
7137 /* now propagate down */
7138 from = to;
7139 }
7140
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01007141 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02007142 return;
7143
Willy Tarreauf6b70012014-12-18 14:00:43 +01007144 if (from->state == PR_STSTOPPED)
7145 return;
7146
Willy Tarreau64ab6072014-09-16 12:17:36 +02007147 /* default_backend */
7148 if (from->defbe.be)
7149 propagate_processes(from, from->defbe.be);
7150
7151 /* use_backend */
7152 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02007153 if (rule->dynamic)
7154 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007155 to = rule->be.backend;
7156 propagate_processes(from, to);
7157 }
Willy Tarreau64ab6072014-09-16 12:17:36 +02007158}
7159
Willy Tarreaubb925012009-07-23 13:36:36 +02007160/*
7161 * Returns the error code, 0 if OK, or any combination of :
7162 * - ERR_ABORT: must abort ASAP
7163 * - ERR_FATAL: we can continue parsing but not start the service
7164 * - ERR_WARN: a warning has been emitted
7165 * - ERR_ALERT: an alert has been emitted
7166 * Only the two first ones can stop processing, the two others are just
7167 * indicators.
7168 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007169int check_config_validity()
7170{
7171 int cfgerr = 0;
7172 struct proxy *curproxy = NULL;
7173 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02007174 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007175 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007176 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007177
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007178 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007179 /*
7180 * Now, check for the integrity of all that we have collected.
7181 */
7182
7183 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02007184 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007185
Willy Tarreau193b8c62012-11-22 00:17:38 +01007186 if (!global.tune.max_http_hdr)
7187 global.tune.max_http_hdr = MAX_HTTP_HDR;
7188
7189 if (!global.tune.cookie_len)
7190 global.tune.cookie_len = CAPTURE_LEN;
7191
7192 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
7193
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007194 /* Post initialisation of the users and groups lists. */
7195 err_code = userlist_postinit();
7196 if (err_code != ERR_NONE)
7197 goto out;
7198
Willy Tarreau55bc0f82009-03-15 14:51:53 +01007199 /* first, we will invert the proxy list order */
7200 curproxy = NULL;
7201 while (proxy) {
7202 struct proxy *next;
7203
7204 next = proxy->next;
7205 proxy->next = curproxy;
7206 curproxy = proxy;
7207 if (!next)
7208 break;
7209 proxy = next;
7210 }
7211
Willy Tarreau419ead82014-09-16 13:41:21 +02007212 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007213 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007214 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01007215 struct sticking_rule *mrule;
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007216 struct act_rule *trule;
7217 struct act_rule *hrqrule;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007218 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01007219 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007220
Willy Tarreau050536d2012-10-04 08:47:34 +02007221 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007222 /* proxy ID not set, use automatic numbering with first
7223 * spare entry starting with next_pxid.
7224 */
7225 next_pxid = get_next_id(&used_proxy_id, next_pxid);
7226 curproxy->conf.id.key = curproxy->uuid = next_pxid;
7227 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007228 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007229 next_pxid++;
7230
Willy Tarreau55ea7572007-06-17 19:56:27 +02007231
Willy Tarreaubaaee002006-06-26 02:48:02 +02007232 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02007233 /* ensure we don't keep listeners uselessly bound */
7234 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02007235 free((void *)curproxy->table.peers.name);
7236 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007237 continue;
7238 }
7239
Willy Tarreau102df612014-05-07 23:56:38 +02007240 /* Check multi-process mode compatibility for the current proxy */
7241
7242 if (curproxy->bind_proc) {
7243 /* an explicit bind-process was specified, let's check how many
7244 * processes remain.
7245 */
David Carliere6c39412015-07-02 07:00:17 +00007246 nbproc = my_popcountl(curproxy->bind_proc);
Willy Tarreau102df612014-05-07 23:56:38 +02007247
7248 curproxy->bind_proc &= nbits(global.nbproc);
7249 if (!curproxy->bind_proc && nbproc == 1) {
7250 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);
7251 curproxy->bind_proc = 1;
7252 }
7253 else if (!curproxy->bind_proc && nbproc > 1) {
7254 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);
7255 curproxy->bind_proc = 0;
7256 }
7257 }
7258
Willy Tarreau3d209582014-05-09 17:06:11 +02007259 /* check and reduce the bind-proc of each listener */
7260 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7261 unsigned long mask;
7262
7263 if (!bind_conf->bind_proc)
7264 continue;
7265
7266 mask = nbits(global.nbproc);
7267 if (curproxy->bind_proc)
7268 mask &= curproxy->bind_proc;
7269 /* mask cannot be null here thanks to the previous checks */
7270
David Carliere6c39412015-07-02 07:00:17 +00007271 nbproc = my_popcountl(bind_conf->bind_proc);
Willy Tarreau3d209582014-05-09 17:06:11 +02007272 bind_conf->bind_proc &= mask;
7273
7274 if (!bind_conf->bind_proc && nbproc == 1) {
7275 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",
7276 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7277 bind_conf->bind_proc = mask & ~(mask - 1);
7278 }
7279 else if (!bind_conf->bind_proc && nbproc > 1) {
7280 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",
7281 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7282 bind_conf->bind_proc = 0;
7283 }
7284 }
7285
Willy Tarreauff01a212009-03-15 13:46:16 +01007286 switch (curproxy->mode) {
7287 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007288 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007289 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007290 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
7291 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007292 cfgerr++;
7293 }
7294
7295 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007296 Warning("config : servers will be ignored for %s '%s'.\n",
7297 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007298 break;
7299
7300 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007301 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007302 break;
7303
7304 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01007305 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01007306 break;
7307 }
7308
Willy Tarreauf3934b82015-08-11 11:36:45 +02007309 if ((curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->conf.listeners)) {
7310 Warning("config : %s '%s' has no 'bind' directive. Please declare it as a backend if this was intended.\n",
7311 proxy_type_str(curproxy), curproxy->id);
7312 err_code |= ERR_WARN;
7313 }
7314
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007315 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007316 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007317 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007318 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
7319 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007320 cfgerr++;
7321 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007322#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007323 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007324 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
7325 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007326 cfgerr++;
7327 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007328#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02007329 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007330 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
7331 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007332 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007333 }
7334 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02007335 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007336 /* If no LB algo is set in a backend, and we're not in
7337 * transparent mode, dispatch mode nor proxy mode, we
7338 * want to use balance roundrobin by default.
7339 */
7340 curproxy->lbprm.algo &= ~BE_LB_ALGO;
7341 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007342 }
7343 }
Willy Tarreau193cf932007-09-17 10:17:23 +02007344
Willy Tarreau1620ec32011-08-06 17:05:02 +02007345 if (curproxy->options & PR_O_DISPATCH)
7346 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
7347 else if (curproxy->options & PR_O_HTTP_PROXY)
7348 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
7349 else if (curproxy->options & PR_O_TRANSP)
7350 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01007351
Willy Tarreau1620ec32011-08-06 17:05:02 +02007352 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
7353 if (curproxy->options & PR_O_DISABLE404) {
7354 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7355 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
7356 err_code |= ERR_WARN;
7357 curproxy->options &= ~PR_O_DISABLE404;
7358 }
7359 if (curproxy->options2 & PR_O2_CHK_SNDST) {
7360 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7361 "send-state", proxy_type_str(curproxy), curproxy->id);
7362 err_code |= ERR_WARN;
7363 curproxy->options &= ~PR_O2_CHK_SNDST;
7364 }
Willy Tarreauef781042010-01-27 11:53:01 +01007365 }
7366
Simon Horman98637e52014-06-20 12:30:16 +09007367 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
7368 if (!global.external_check) {
7369 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
7370 curproxy->id, "option external-check");
7371 cfgerr++;
7372 }
7373 if (!curproxy->check_command) {
7374 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
7375 curproxy->id, "option external-check");
7376 cfgerr++;
7377 }
7378 }
7379
Simon Horman64e34162015-02-06 11:11:57 +09007380 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007381 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
7382 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Pieter Baauw8669e972015-08-17 00:45:05 +02007383 "'email-alert from', 'email-alert level' 'email-alert mailers', "
7384 "'email-alert myhostname', or 'email-alert to' "
7385 "requires each of 'email-alert from', 'email-alert mailers' and 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007386 "to be present).\n",
7387 proxy_type_str(curproxy), curproxy->id);
7388 err_code |= ERR_WARN;
7389 free_email_alert(curproxy);
7390 }
7391 if (!curproxy->email_alert.myhostname)
7392 curproxy->email_alert.myhostname = hostname;
Simon Horman9dc49962015-01-30 11:22:59 +09007393 }
7394
Simon Horman98637e52014-06-20 12:30:16 +09007395 if (curproxy->check_command) {
7396 int clear = 0;
7397 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7398 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7399 "external-check command", proxy_type_str(curproxy), curproxy->id);
7400 err_code |= ERR_WARN;
7401 clear = 1;
7402 }
7403 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
7404 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-command path' is not set.\n",
7405 curproxy->id, "external-check command");
7406 cfgerr++;
7407 }
7408 if (clear) {
7409 free(curproxy->check_command);
7410 curproxy->check_command = NULL;
7411 }
7412 }
7413
7414 if (curproxy->check_path) {
7415 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7416 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7417 "external-check path", proxy_type_str(curproxy), curproxy->id);
7418 err_code |= ERR_WARN;
7419 free(curproxy->check_path);
7420 curproxy->check_path = NULL;
7421 }
7422 }
7423
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007424 /* if a default backend was specified, let's find it */
7425 if (curproxy->defbe.name) {
7426 struct proxy *target;
7427
Willy Tarreauafb39922015-05-26 12:04:09 +02007428 target = proxy_be_by_name(curproxy->defbe.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007429 if (!target) {
7430 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
7431 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007432 cfgerr++;
7433 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007434 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
7435 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02007436 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007437 } else if (target->mode != curproxy->mode &&
7438 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7439
7440 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) as its default backend (see 'mode').\n",
7441 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7442 curproxy->conf.file, curproxy->conf.line,
7443 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7444 target->conf.file, target->conf.line);
7445 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007446 } else {
7447 free(curproxy->defbe.name);
7448 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01007449
7450 /* Emit a warning if this proxy also has some servers */
7451 if (curproxy->srv) {
7452 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
7453 curproxy->id);
7454 err_code |= ERR_WARN;
7455 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007456 }
7457 }
7458
Willy Tarreau55ea7572007-06-17 19:56:27 +02007459 /* find the target proxy for 'use_backend' rules */
7460 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007461 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007462 struct logformat_node *node;
7463 char *pxname;
7464
7465 /* Try to parse the string as a log format expression. If the result
7466 * of the parsing is only one entry containing a simple string, then
7467 * it's a standard string corresponding to a static rule, thus the
7468 * parsing is cancelled and be.name is restored to be resolved.
7469 */
7470 pxname = rule->be.name;
7471 LIST_INIT(&rule->be.expr);
7472 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
7473 curproxy->conf.args.file, curproxy->conf.args.line);
7474 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
7475
7476 if (!LIST_ISEMPTY(&rule->be.expr)) {
7477 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
7478 rule->dynamic = 1;
7479 free(pxname);
7480 continue;
7481 }
7482 /* simple string: free the expression and fall back to static rule */
7483 free(node->arg);
7484 free(node);
7485 }
7486
7487 rule->dynamic = 0;
7488 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007489
Willy Tarreauafb39922015-05-26 12:04:09 +02007490 target = proxy_be_by_name(rule->be.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007491 if (!target) {
7492 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
7493 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007494 cfgerr++;
7495 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007496 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
7497 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007498 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007499 } else if (target->mode != curproxy->mode &&
7500 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7501
7502 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) in a 'use_backend' rule (see 'mode').\n",
7503 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7504 curproxy->conf.file, curproxy->conf.line,
7505 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7506 target->conf.file, target->conf.line);
7507 cfgerr++;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007508 } else {
7509 free((void *)rule->be.name);
7510 rule->be.backend = target;
7511 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007512 }
7513
Willy Tarreau64ab6072014-09-16 12:17:36 +02007514 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007515 list_for_each_entry(srule, &curproxy->server_rules, list) {
7516 struct server *target = findserver(curproxy, srule->srv.name);
7517
7518 if (!target) {
7519 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7520 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7521 cfgerr++;
7522 continue;
7523 }
7524 free((void *)srule->srv.name);
7525 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007526 }
7527
Emeric Brunb982a3d2010-01-04 15:45:53 +01007528 /* find the target table for 'stick' rules */
7529 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7530 struct proxy *target;
7531
Emeric Brun1d33b292010-01-04 15:47:17 +01007532 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7533 if (mrule->flags & STK_IS_STORE)
7534 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7535
Emeric Brunb982a3d2010-01-04 15:45:53 +01007536 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007537 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007538 else
7539 target = curproxy;
7540
7541 if (!target) {
7542 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7543 curproxy->id, mrule->table.name);
7544 cfgerr++;
7545 }
7546 else if (target->table.size == 0) {
7547 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7548 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7549 cfgerr++;
7550 }
Willy Tarreau12785782012-04-27 21:37:17 +02007551 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7552 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007553 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7554 cfgerr++;
7555 }
7556 else {
7557 free((void *)mrule->table.name);
7558 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007559 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007560 }
7561 }
7562
7563 /* find the target table for 'store response' rules */
7564 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7565 struct proxy *target;
7566
Emeric Brun1d33b292010-01-04 15:47:17 +01007567 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7568
Emeric Brunb982a3d2010-01-04 15:45:53 +01007569 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007570 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007571 else
7572 target = curproxy;
7573
7574 if (!target) {
7575 Alert("Proxy '%s': unable to find store table '%s'.\n",
7576 curproxy->id, mrule->table.name);
7577 cfgerr++;
7578 }
7579 else if (target->table.size == 0) {
7580 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7581 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7582 cfgerr++;
7583 }
Willy Tarreau12785782012-04-27 21:37:17 +02007584 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7585 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007586 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7587 cfgerr++;
7588 }
7589 else {
7590 free((void *)mrule->table.name);
7591 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007592 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007593 }
7594 }
7595
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007596 /* find the target table for 'tcp-request' layer 4 rules */
7597 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
7598 struct proxy *target;
7599
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007600 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007601 continue;
7602
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007603 if (trule->arg.trk_ctr.table.n)
7604 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007605 else
7606 target = curproxy;
7607
7608 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007609 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007610 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007611 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007612 cfgerr++;
7613 }
7614 else if (target->table.size == 0) {
7615 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007616 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007617 cfgerr++;
7618 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007619 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007620 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007621 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007622 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007623 cfgerr++;
7624 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007625 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007626 free(trule->arg.trk_ctr.table.n);
7627 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007628 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007629 * to pass a list of counters to track and allocate them right here using
7630 * stktable_alloc_data_type().
7631 */
7632 }
7633 }
7634
Willy Tarreaud1f96522010-08-03 19:34:32 +02007635 /* find the target table for 'tcp-request' layer 6 rules */
7636 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7637 struct proxy *target;
7638
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007639 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02007640 continue;
7641
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007642 if (trule->arg.trk_ctr.table.n)
7643 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007644 else
7645 target = curproxy;
7646
7647 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007648 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007649 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007650 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02007651 cfgerr++;
7652 }
7653 else if (target->table.size == 0) {
7654 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007655 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007656 cfgerr++;
7657 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007658 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007659 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007660 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007661 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007662 cfgerr++;
7663 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02007664 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007665 free(trule->arg.trk_ctr.table.n);
7666 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007667 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02007668 * to pass a list of counters to track and allocate them right here using
7669 * stktable_alloc_data_type().
7670 */
7671 }
7672 }
7673
Willy Tarreau09448f72014-06-25 18:12:15 +02007674 /* find the target table for 'http-request' layer 7 rules */
7675 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7676 struct proxy *target;
7677
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007678 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau09448f72014-06-25 18:12:15 +02007679 continue;
7680
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007681 if (hrqrule->arg.trk_ctr.table.n)
7682 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
Willy Tarreau09448f72014-06-25 18:12:15 +02007683 else
7684 target = curproxy;
7685
7686 if (!target) {
7687 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007688 curproxy->id, hrqrule->arg.trk_ctr.table.n,
Willy Tarreau09448f72014-06-25 18:12:15 +02007689 http_req_trk_idx(hrqrule->action));
7690 cfgerr++;
7691 }
7692 else if (target->table.size == 0) {
7693 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007694 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau09448f72014-06-25 18:12:15 +02007695 cfgerr++;
7696 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007697 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau09448f72014-06-25 18:12:15 +02007698 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007699 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau09448f72014-06-25 18:12:15 +02007700 http_req_trk_idx(hrqrule->action));
7701 cfgerr++;
7702 }
7703 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007704 free(hrqrule->arg.trk_ctr.table.n);
7705 hrqrule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau09448f72014-06-25 18:12:15 +02007706 /* Note: if we decide to enhance the track-sc syntax, we may be able
7707 * to pass a list of counters to track and allocate them right here using
7708 * stktable_alloc_data_type().
7709 */
7710 }
7711 }
7712
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02007713 /* move any "block" rules at the beginning of the http-request rules */
7714 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
7715 /* insert block_rules into http_req_rules at the beginning */
7716 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
7717 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
7718 curproxy->block_rules.n->p = &curproxy->http_req_rules;
7719 curproxy->http_req_rules.n = curproxy->block_rules.n;
7720 LIST_INIT(&curproxy->block_rules);
7721 }
7722
Emeric Brun32da3c42010-09-23 18:39:19 +02007723 if (curproxy->table.peers.name) {
7724 struct peers *curpeers = peers;
7725
7726 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
7727 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
7728 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01007729 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02007730 break;
7731 }
7732 }
7733
7734 if (!curpeers) {
7735 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
7736 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007737 free((void *)curproxy->table.peers.name);
7738 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007739 cfgerr++;
7740 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02007741 else if (curpeers->state == PR_STSTOPPED) {
7742 /* silently disable this peers section */
7743 curproxy->table.peers.p = NULL;
7744 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007745 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02007746 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
7747 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007748 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007749 cfgerr++;
7750 }
7751 }
7752
Simon Horman9dc49962015-01-30 11:22:59 +09007753
7754 if (curproxy->email_alert.mailers.name) {
7755 struct mailers *curmailers = mailers;
7756
7757 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
7758 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
7759 free(curproxy->email_alert.mailers.name);
7760 curproxy->email_alert.mailers.m = curmailers;
7761 curmailers->users++;
7762 break;
7763 }
7764 }
7765
7766 if (!curmailers) {
7767 Alert("Proxy '%s': unable to find mailers '%s'.\n",
7768 curproxy->id, curproxy->email_alert.mailers.name);
7769 free_email_alert(curproxy);
7770 cfgerr++;
7771 }
7772 }
7773
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007774 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01007775 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007776 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
7777 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
7778 "proxy", curproxy->id);
7779 cfgerr++;
7780 goto out_uri_auth_compat;
7781 }
7782
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007783 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007784 const char *uri_auth_compat_req[10];
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007785 struct act_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01007786 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007787
Willy Tarreau95fa4692010-02-01 13:05:50 +01007788 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
7789 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007790
7791 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007792 uri_auth_compat_req[i++] = "realm";
7793 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
7794 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007795
Willy Tarreau95fa4692010-02-01 13:05:50 +01007796 uri_auth_compat_req[i++] = "unless";
7797 uri_auth_compat_req[i++] = "{";
7798 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
7799 uri_auth_compat_req[i++] = "}";
7800 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007801
Willy Tarreauff011f22011-01-06 17:51:27 +01007802 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
7803 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007804 cfgerr++;
7805 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007806 }
7807
Willy Tarreauff011f22011-01-06 17:51:27 +01007808 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01007809
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007810 if (curproxy->uri_auth->auth_realm) {
7811 free(curproxy->uri_auth->auth_realm);
7812 curproxy->uri_auth->auth_realm = NULL;
7813 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007814
7815 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007816 }
7817out_uri_auth_compat:
7818
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007819 /* compile the log format */
7820 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02007821 if (curproxy->conf.logformat_string != default_http_log_format &&
7822 curproxy->conf.logformat_string != default_tcp_log_format &&
7823 curproxy->conf.logformat_string != clf_http_log_format)
7824 free(curproxy->conf.logformat_string);
7825 curproxy->conf.logformat_string = NULL;
7826 free(curproxy->conf.lfs_file);
7827 curproxy->conf.lfs_file = NULL;
7828 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007829 }
7830
Willy Tarreau62a61232013-04-12 18:13:46 +02007831 if (curproxy->conf.logformat_string) {
7832 curproxy->conf.args.ctx = ARGC_LOG;
7833 curproxy->conf.args.file = curproxy->conf.lfs_file;
7834 curproxy->conf.args.line = curproxy->conf.lfs_line;
7835 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007836 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007837 curproxy->conf.args.file = NULL;
7838 curproxy->conf.args.line = 0;
7839 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007840
Willy Tarreau62a61232013-04-12 18:13:46 +02007841 if (curproxy->conf.uniqueid_format_string) {
7842 curproxy->conf.args.ctx = ARGC_UIF;
7843 curproxy->conf.args.file = curproxy->conf.uif_file;
7844 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01007845 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Godbachd9722032014-12-18 15:44:58 +08007846 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007847 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007848 curproxy->conf.args.file = NULL;
7849 curproxy->conf.args.line = 0;
7850 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007851
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007852 /* only now we can check if some args remain unresolved.
7853 * This must be done after the users and groups resolution.
7854 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007855 cfgerr += smp_resolve_args(curproxy);
7856 if (!cfgerr)
7857 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01007858
Willy Tarreau2738a142006-07-08 17:28:09 +02007859 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007860 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02007861 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02007862 (!curproxy->timeout.connect ||
7863 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007864 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02007865 " | While not properly invalid, you will certainly encounter various problems\n"
7866 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01007867 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007868 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007869 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02007870 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02007871
Willy Tarreau1fa31262007-12-03 00:36:16 +01007872 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
7873 * We must still support older configurations, so let's find out whether those
7874 * parameters have been set or must be copied from contimeouts.
7875 */
7876 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007877 if (!curproxy->timeout.tarpit ||
7878 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007879 /* tarpit timeout not set. We search in the following order:
7880 * default.tarpit, curr.connect, default.connect.
7881 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007882 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007883 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007884 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007885 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007886 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007887 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007888 }
7889 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007890 (!curproxy->timeout.queue ||
7891 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007892 /* queue timeout not set. We search in the following order:
7893 * default.queue, curr.connect, default.connect.
7894 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007895 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007896 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007897 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007898 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007899 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007900 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007901 }
7902 }
7903
Willy Tarreau1620ec32011-08-06 17:05:02 +02007904 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01007905 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
7906 curproxy->check_req = (char *)malloc(curproxy->check_len);
7907 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02007908 }
7909
Willy Tarreau215663d2014-06-13 18:30:23 +02007910 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
7911 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
7912 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
7913 proxy_type_str(curproxy), curproxy->id);
7914 err_code |= ERR_WARN;
7915 }
7916
Willy Tarreau193b8c62012-11-22 00:17:38 +01007917 /* ensure that cookie capture length is not too large */
7918 if (curproxy->capture_len >= global.tune.cookie_len) {
7919 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
7920 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
7921 err_code |= ERR_WARN;
7922 curproxy->capture_len = global.tune.cookie_len - 1;
7923 }
7924
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007925 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01007926 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02007927 curproxy->req_cap_pool = create_pool("ptrcap",
7928 curproxy->nb_req_cap * sizeof(char *),
7929 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01007930 }
7931
7932 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02007933 curproxy->rsp_cap_pool = create_pool("ptrcap",
7934 curproxy->nb_rsp_cap * sizeof(char *),
7935 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01007936 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007937
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02007938 switch (curproxy->load_server_state_from_file) {
7939 case PR_SRV_STATE_FILE_UNSPEC:
7940 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
7941 break;
7942 case PR_SRV_STATE_FILE_GLOBAL:
7943 if (!global.server_state_file) {
7944 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",
7945 curproxy->id);
7946 err_code |= ERR_WARN;
7947 }
7948 break;
7949 }
7950
Willy Tarreaubaaee002006-06-26 02:48:02 +02007951 /* first, we will invert the servers list order */
7952 newsrv = NULL;
7953 while (curproxy->srv) {
7954 struct server *next;
7955
7956 next = curproxy->srv->next;
7957 curproxy->srv->next = newsrv;
7958 newsrv = curproxy->srv;
7959 if (!next)
7960 break;
7961 curproxy->srv = next;
7962 }
7963
Willy Tarreau17edc812014-01-03 12:14:34 +01007964 /* Check that no server name conflicts. This causes trouble in the stats.
7965 * We only emit a warning for the first conflict affecting each server,
7966 * in order to avoid combinatory explosion if all servers have the same
7967 * name. We do that only for servers which do not have an explicit ID,
7968 * because these IDs were made also for distinguishing them and we don't
7969 * want to annoy people who correctly manage them.
7970 */
7971 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
7972 struct server *other_srv;
7973
7974 if (newsrv->puid)
7975 continue;
7976
7977 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
7978 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
7979 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
7980 newsrv->conf.file, newsrv->conf.line,
7981 proxy_type_str(curproxy), curproxy->id,
7982 newsrv->id, other_srv->conf.line);
7983 break;
7984 }
7985 }
7986 }
7987
Willy Tarreaudd701652010-05-25 23:03:02 +02007988 /* assign automatic UIDs to servers which don't have one yet */
7989 next_id = 1;
7990 newsrv = curproxy->srv;
7991 while (newsrv != NULL) {
7992 if (!newsrv->puid) {
7993 /* server ID not set, use automatic numbering with first
7994 * spare entry starting with next_svid.
7995 */
7996 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
7997 newsrv->conf.id.key = newsrv->puid = next_id;
7998 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
7999 }
8000 next_id++;
8001 newsrv = newsrv->next;
8002 }
8003
Willy Tarreau20697042007-11-15 23:26:18 +01008004 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01008005 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02008006
Willy Tarreau62c3be22012-01-20 13:12:32 +01008007 /*
8008 * If this server supports a maxconn parameter, it needs a dedicated
8009 * tasks to fill the emptied slots when a connection leaves.
8010 * Also, resolve deferred tracking dependency if needed.
8011 */
8012 newsrv = curproxy->srv;
8013 while (newsrv != NULL) {
8014 if (newsrv->minconn > newsrv->maxconn) {
8015 /* Only 'minconn' was specified, or it was higher than or equal
8016 * to 'maxconn'. Let's turn this into maxconn and clean it, as
8017 * this will avoid further useless expensive computations.
8018 */
8019 newsrv->maxconn = newsrv->minconn;
8020 } else if (newsrv->maxconn && !newsrv->minconn) {
8021 /* minconn was not specified, so we set it to maxconn */
8022 newsrv->minconn = newsrv->maxconn;
8023 }
8024
Emeric Brun01f8e2f2012-05-18 16:02:00 +02008025#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02008026 if (newsrv->use_ssl || newsrv->check.use_ssl)
8027 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02008028#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02008029
Willy Tarreau2f075e92013-12-03 11:11:34 +01008030 /* set the check type on the server */
8031 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
8032
Willy Tarreau62c3be22012-01-20 13:12:32 +01008033 if (newsrv->trackit) {
8034 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02008035 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008036 char *pname, *sname;
8037
8038 pname = newsrv->trackit;
8039 sname = strrchr(pname, '/');
8040
8041 if (sname)
8042 *sname++ = '\0';
8043 else {
8044 sname = pname;
8045 pname = NULL;
8046 }
8047
8048 if (pname) {
Willy Tarreau9e0bb102015-05-26 11:24:42 +02008049 px = proxy_be_by_name(pname);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008050 if (!px) {
8051 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
8052 proxy_type_str(curproxy), curproxy->id,
8053 newsrv->id, pname);
8054 cfgerr++;
8055 goto next_srv;
8056 }
8057 } else
8058 px = curproxy;
8059
8060 srv = findserver(px, sname);
8061 if (!srv) {
8062 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
8063 proxy_type_str(curproxy), curproxy->id,
8064 newsrv->id, sname);
8065 cfgerr++;
8066 goto next_srv;
8067 }
8068
Willy Tarreau32091232014-05-16 13:52:00 +02008069 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
8070 !(srv->agent.state & CHK_ST_CONFIGURED) &&
8071 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01008072 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02008073 "tracking as it does not have any check nor agent enabled.\n",
8074 proxy_type_str(curproxy), curproxy->id,
8075 newsrv->id, px->id, srv->id);
8076 cfgerr++;
8077 goto next_srv;
8078 }
8079
8080 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
8081
8082 if (loop) {
8083 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
8084 "belongs to a tracking chain looping back to %s/%s.\n",
8085 proxy_type_str(curproxy), curproxy->id,
8086 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008087 cfgerr++;
8088 goto next_srv;
8089 }
8090
8091 if (curproxy != px &&
8092 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
8093 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
8094 "tracking: disable-on-404 option inconsistency.\n",
8095 proxy_type_str(curproxy), curproxy->id,
8096 newsrv->id, px->id, srv->id);
8097 cfgerr++;
8098 goto next_srv;
8099 }
8100
8101 /* if the other server is forced disabled, we have to do the same here */
Willy Tarreau20125212014-05-13 19:44:56 +02008102 if (srv->admin & SRV_ADMF_MAINT) {
Willy Tarreaua0066dd2014-05-16 11:25:16 +02008103 newsrv->admin |= SRV_ADMF_IMAINT;
Willy Tarreau892337c2014-05-13 23:41:20 +02008104 newsrv->state = SRV_ST_STOPPED;
Simon Horman125d0992013-02-24 17:23:38 +09008105 newsrv->check.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008106 }
8107
8108 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01008109 newsrv->tracknext = srv->trackers;
8110 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008111
8112 free(newsrv->trackit);
8113 newsrv->trackit = NULL;
8114 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008115
8116 /*
8117 * resolve server's resolvers name and update the resolvers pointer
8118 * accordingly
8119 */
8120 if (newsrv->resolvers_id) {
8121 struct dns_resolvers *curr_resolvers;
8122 int found;
8123
8124 found = 0;
8125 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
8126 if (!strcmp(curr_resolvers->id, newsrv->resolvers_id)) {
8127 found = 1;
8128 break;
8129 }
8130 }
8131
8132 if (!found) {
8133 Alert("config : %s '%s', server '%s': unable to find required resolvers '%s'\n",
8134 proxy_type_str(curproxy), curproxy->id,
8135 newsrv->id, newsrv->resolvers_id);
8136 cfgerr++;
8137 } else {
8138 free(newsrv->resolvers_id);
8139 newsrv->resolvers_id = NULL;
8140 if (newsrv->resolution)
8141 newsrv->resolution->resolvers = curr_resolvers;
8142 }
8143 }
8144 else {
8145 /* if no resolvers section associated to this server
8146 * we can clean up the associated resolution structure
8147 */
8148 if (newsrv->resolution) {
8149 free(newsrv->resolution->hostname_dn);
8150 newsrv->resolution->hostname_dn = NULL;
8151 free(newsrv->resolution);
8152 newsrv->resolution = NULL;
8153 }
8154 }
8155
Willy Tarreau62c3be22012-01-20 13:12:32 +01008156 next_srv:
8157 newsrv = newsrv->next;
8158 }
8159
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008160 /* We have to initialize the server lookup mechanism depending
8161 * on what LB algorithm was choosen.
8162 */
8163
8164 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
8165 switch (curproxy->lbprm.algo & BE_LB_KIND) {
8166 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02008167 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
8168 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8169 init_server_map(curproxy);
8170 } else {
8171 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
8172 fwrr_init_server_groups(curproxy);
8173 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008174 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008175
Willy Tarreau3ebb1162012-02-13 16:57:44 +01008176 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01008177 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
8178 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
8179 fwlc_init_server_tree(curproxy);
8180 } else {
8181 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
8182 fas_init_server_tree(curproxy);
8183 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008184 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008185
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008186 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008187 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
8188 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
8189 chash_init_server_tree(curproxy);
8190 } else {
8191 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8192 init_server_map(curproxy);
8193 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008194 break;
8195 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02008196
8197 if (curproxy->options & PR_O_LOGASAP)
8198 curproxy->to_log &= ~LW_BYTES;
8199
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008200 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01008201 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008202 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
8203 proxy_type_str(curproxy), curproxy->id);
8204 err_code |= ERR_WARN;
8205 }
8206
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008207 if (curproxy->mode != PR_MODE_HTTP) {
8208 int optnum;
8209
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008210 if (curproxy->uri_auth) {
8211 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
8212 proxy_type_str(curproxy), curproxy->id);
8213 err_code |= ERR_WARN;
8214 curproxy->uri_auth = NULL;
8215 }
8216
Willy Tarreau87cf5142011-08-19 22:57:24 +02008217 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008218 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8219 "forwardfor", proxy_type_str(curproxy), curproxy->id);
8220 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02008221 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008222 }
8223
8224 if (curproxy->options & PR_O_ORGTO) {
8225 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8226 "originalto", proxy_type_str(curproxy), curproxy->id);
8227 err_code |= ERR_WARN;
8228 curproxy->options &= ~PR_O_ORGTO;
8229 }
8230
8231 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
8232 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
8233 (curproxy->cap & cfg_opts[optnum].cap) &&
8234 (curproxy->options & cfg_opts[optnum].val)) {
8235 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8236 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
8237 err_code |= ERR_WARN;
8238 curproxy->options &= ~cfg_opts[optnum].val;
8239 }
8240 }
8241
8242 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
8243 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
8244 (curproxy->cap & cfg_opts2[optnum].cap) &&
8245 (curproxy->options2 & cfg_opts2[optnum].val)) {
8246 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8247 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
8248 err_code |= ERR_WARN;
8249 curproxy->options2 &= ~cfg_opts2[optnum].val;
8250 }
8251 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008252
Willy Tarreau29fbe512015-08-20 19:35:14 +02008253#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008254 if (curproxy->conn_src.bind_hdr_occ) {
8255 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008256 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01008257 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008258 err_code |= ERR_WARN;
8259 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008260#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008261 }
8262
Willy Tarreaubaaee002006-06-26 02:48:02 +02008263 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01008264 * ensure that we're not cross-dressing a TCP server into HTTP.
8265 */
8266 newsrv = curproxy->srv;
8267 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01008268 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008269 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
8270 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008271 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01008272 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008273
Willy Tarreau0cec3312011-10-31 13:49:26 +01008274 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
8275 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
8276 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8277 err_code |= ERR_WARN;
8278 }
8279
Willy Tarreauc93cd162014-05-13 15:54:22 +02008280 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02008281 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
8282 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8283 err_code |= ERR_WARN;
8284 }
8285
Willy Tarreau29fbe512015-08-20 19:35:14 +02008286#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008287 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
8288 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008289 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 +01008290 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008291 err_code |= ERR_WARN;
8292 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008293#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01008294 newsrv = newsrv->next;
8295 }
8296
Willy Tarreaue42bd962014-09-16 16:21:19 +02008297 /* check if we have a frontend with "tcp-request content" looking at L7
8298 * with no inspect-delay
8299 */
8300 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
8301 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008302 if (trule->action == ACT_TCP_CAPTURE &&
Thierry FOURNIERd0d65ae2015-08-04 08:21:12 +02008303 !(trule->arg.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008304 break;
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008305 if ((trule->action >= ACT_ACTION_TRK_SC0 && trule->action <= ACT_ACTION_TRK_SCMAX) &&
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008306 !(trule->arg.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008307 break;
8308 }
8309
8310 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
8311 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
8312 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
8313 " This means that these rules will randomly find their contents. This can be fixed by"
8314 " setting the tcp-request inspect-delay.\n",
8315 proxy_type_str(curproxy), curproxy->id);
8316 err_code |= ERR_WARN;
8317 }
8318 }
8319
Willy Tarreauc1a21672009-08-16 22:37:44 +02008320 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02008321 if (!curproxy->accept)
8322 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02008323
Willy Tarreauc1a21672009-08-16 22:37:44 +02008324 if (curproxy->tcp_req.inspect_delay ||
8325 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02008326 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008327
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008328 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008329 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008330 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008331 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008332
8333 /* both TCP and HTTP must check switching rules */
8334 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
8335 }
8336
8337 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02008338 if (curproxy->tcp_req.inspect_delay ||
8339 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
8340 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
8341
Emeric Brun97679e72010-09-23 17:56:44 +02008342 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
8343 curproxy->be_rsp_ana |= AN_RES_INSPECT;
8344
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008345 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008346 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008347 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008348 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008349
8350 /* If the backend does requires RDP cookie persistence, we have to
8351 * enable the corresponding analyser.
8352 */
8353 if (curproxy->options2 & PR_O2_RDPC_PRST)
8354 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
8355 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008356 }
8357
8358 /***********************************************************/
8359 /* At this point, target names have already been resolved. */
8360 /***********************************************************/
8361
8362 /* Check multi-process mode compatibility */
8363
8364 if (global.nbproc > 1 && global.stats_fe) {
8365 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8366 unsigned long mask;
8367
8368 mask = nbits(global.nbproc);
8369 if (global.stats_fe->bind_proc)
8370 mask &= global.stats_fe->bind_proc;
8371
8372 if (bind_conf->bind_proc)
8373 mask &= bind_conf->bind_proc;
8374
8375 /* stop here if more than one process is used */
David Carliere6c39412015-07-02 07:00:17 +00008376 if (my_popcountl(mask) > 1)
Willy Tarreau419ead82014-09-16 13:41:21 +02008377 break;
8378 }
8379 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
8380 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");
8381 }
8382 }
8383
8384 /* Make each frontend inherit bind-process from its listeners when not specified. */
8385 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8386 if (curproxy->bind_proc)
8387 continue;
8388
8389 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8390 unsigned long mask;
8391
Willy Tarreaue428b082015-05-04 21:57:58 +02008392 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008393 curproxy->bind_proc |= mask;
8394 }
8395
8396 if (!curproxy->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008397 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008398 }
8399
8400 if (global.stats_fe) {
8401 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8402 unsigned long mask;
8403
Willy Tarreaue428b082015-05-04 21:57:58 +02008404 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008405 global.stats_fe->bind_proc |= mask;
8406 }
8407 if (!global.stats_fe->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008408 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008409 }
8410
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02008411 /* propagate bindings from frontends to backends. Don't do it if there
8412 * are any fatal errors as we must not call it with unresolved proxies.
8413 */
8414 if (!cfgerr) {
8415 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8416 if (curproxy->cap & PR_CAP_FE)
8417 propagate_processes(curproxy, NULL);
8418 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008419 }
8420
8421 /* Bind each unbound backend to all processes when not specified. */
8422 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8423 if (curproxy->bind_proc)
8424 continue;
Willy Tarreaue428b082015-05-04 21:57:58 +02008425 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008426 }
8427
8428 /*******************************************************/
8429 /* At this step, all proxies have a non-null bind_proc */
8430 /*******************************************************/
8431
8432 /* perform the final checks before creating tasks */
8433
8434 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8435 struct listener *listener;
8436 unsigned int next_id;
8437 int nbproc;
8438
David Carliere6c39412015-07-02 07:00:17 +00008439 nbproc = my_popcountl(curproxy->bind_proc & nbits(global.nbproc));
Willy Tarreauc1a21672009-08-16 22:37:44 +02008440
Emeric Brunc52962f2012-11-15 18:28:02 +01008441#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008442 /* Configure SSL for each bind line.
8443 * Note: if configuration fails at some point, the ->ctx member
8444 * remains NULL so that listeners can later detach.
8445 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008446 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008447 int alloc_ctx;
8448
Emeric Brunc52962f2012-11-15 18:28:02 +01008449 if (!bind_conf->is_ssl) {
8450 if (bind_conf->default_ctx) {
8451 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
8452 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
8453 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008454 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01008455 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008456 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02008457 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008458 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008459 cfgerr++;
8460 continue;
8461 }
8462
Emeric Brun8dc60392014-05-09 13:52:00 +02008463 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008464 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02008465 if (alloc_ctx == SHCTX_E_INIT_LOCK)
8466 Alert("Unable to initialize the lock for the shared SSL session cache. You can retry using the global statement 'tune.ssl.force-private-cache' but it could increase CPU usage due to renegotiations if nbproc > 1.\n");
8467 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008468 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02008469 cfgerr++;
8470 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008471 }
8472
Emeric Brunfc0421f2012-09-07 17:30:07 +02008473 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008474 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008475
8476 /* initialize CA variables if the certificates generation is enabled */
8477 cfgerr += ssl_sock_load_ca(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008478 }
Emeric Brunc52962f2012-11-15 18:28:02 +01008479#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008480
Willy Tarreaue6b98942007-10-29 01:09:36 +01008481 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008482 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008483 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008484 if (!listener->luid) {
8485 /* listener ID not set, use automatic numbering with first
8486 * spare entry starting with next_luid.
8487 */
8488 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
8489 listener->conf.id.key = listener->luid = next_id;
8490 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008491 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01008492 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008493
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008494 /* enable separate counters */
8495 if (curproxy->options2 & PR_O2_SOCKSTAT) {
8496 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01008497 if (!listener->name)
8498 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008499 }
Willy Tarreau81796be2012-09-22 19:11:47 +02008500
Willy Tarreaue6b98942007-10-29 01:09:36 +01008501 if (curproxy->options & PR_O_TCP_NOLING)
8502 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02008503 if (!listener->maxconn)
8504 listener->maxconn = curproxy->maxconn;
8505 if (!listener->backlog)
8506 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01008507 if (!listener->maxaccept)
8508 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
8509
8510 /* we want to have an optimal behaviour on single process mode to
8511 * maximize the work at once, but in multi-process we want to keep
8512 * some fairness between processes, so we target half of the max
8513 * number of events to be balanced over all the processes the proxy
8514 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
8515 * used to disable the limit.
8516 */
8517 if (listener->maxaccept > 0) {
8518 if (nbproc > 1)
8519 listener->maxaccept = (listener->maxaccept + 1) / 2;
8520 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
8521 }
8522
Willy Tarreau9903f0e2015-04-04 18:50:31 +02008523 listener->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02008524 listener->handler = process_stream;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008525 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01008526 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01008527
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008528 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
8529 listener->options |= LI_O_TCP_RULES;
8530
Willy Tarreaude3041d2010-05-31 10:56:17 +02008531 if (curproxy->mon_mask.s_addr)
8532 listener->options |= LI_O_CHK_MONNET;
8533
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008534 /* smart accept mode is automatic in HTTP mode */
8535 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008536 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008537 !(curproxy->no_options2 & PR_O2_SMARTACC)))
8538 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01008539 }
8540
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008541 /* Release unused SSL configs */
8542 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8543 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008544 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008545#ifdef USE_OPENSSL
Christopher Faulet31af49d2015-06-09 17:29:50 +02008546 ssl_sock_free_ca(bind_conf);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008547 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008548 free(bind_conf->ca_file);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008549 free(bind_conf->ca_sign_file);
8550 free(bind_conf->ca_sign_pass);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008551 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02008552 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008553 free(bind_conf->crl_file);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008554 if(bind_conf->keys_ref) {
8555 free(bind_conf->keys_ref->filename);
8556 free(bind_conf->keys_ref->tlskeys);
8557 free(bind_conf->keys_ref);
8558 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008559#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008560 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008561
Willy Tarreau102df612014-05-07 23:56:38 +02008562 if (nbproc > 1) {
8563 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02008564 int count, maxproc = 0;
8565
8566 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
David Carliere6c39412015-07-02 07:00:17 +00008567 count = my_popcountl(bind_conf->bind_proc);
Willy Tarreaueb791e02014-09-16 15:11:04 +02008568 if (count > maxproc)
8569 maxproc = count;
8570 }
8571 /* backends have 0, frontends have 1 or more */
8572 if (maxproc != 1)
8573 Warning("Proxy '%s': in multi-process mode, stats will be"
8574 " limited to process assigned to the current request.\n",
8575 curproxy->id);
8576
Willy Tarreau102df612014-05-07 23:56:38 +02008577 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
8578 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
8579 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008580 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008581 }
Willy Tarreau102df612014-05-07 23:56:38 +02008582 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
8583 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
8584 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008585 }
8586 }
Willy Tarreau918ff602011-07-25 16:33:49 +02008587
8588 /* create the task associated with the proxy */
8589 curproxy->task = task_new();
8590 if (curproxy->task) {
8591 curproxy->task->context = curproxy;
8592 curproxy->task->process = manage_proxy;
8593 /* no need to queue, it will be done automatically if some
8594 * listener gets limited.
8595 */
8596 curproxy->task->expire = TICK_ETERNITY;
8597 } else {
8598 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
8599 curproxy->id);
8600 cfgerr++;
8601 }
Willy Tarreaub369a042014-09-16 13:21:03 +02008602 }
8603
Willy Tarreaufbb78422011-06-05 15:38:35 +02008604 /* automatically compute fullconn if not set. We must not do it in the
8605 * loop above because cross-references are not yet fully resolved.
8606 */
8607 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8608 /* If <fullconn> is not set, let's set it to 10% of the sum of
8609 * the possible incoming frontend's maxconns.
8610 */
8611 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
8612 struct proxy *fe;
8613 int total = 0;
8614
8615 /* sum up the number of maxconns of frontends which
8616 * reference this backend at least once or which are
8617 * the same one ('listen').
8618 */
8619 for (fe = proxy; fe; fe = fe->next) {
8620 struct switching_rule *rule;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008621 int found = 0;
8622
8623 if (!(fe->cap & PR_CAP_FE))
8624 continue;
8625
8626 if (fe == curproxy) /* we're on a "listen" instance */
8627 found = 1;
8628
8629 if (fe->defbe.be == curproxy) /* "default_backend" */
8630 found = 1;
8631
8632 /* check if a "use_backend" rule matches */
8633 if (!found) {
8634 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01008635 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02008636 found = 1;
8637 break;
8638 }
8639 }
8640 }
8641
Willy Tarreaufbb78422011-06-05 15:38:35 +02008642 /* now we've checked all possible ways to reference a backend
8643 * from a frontend.
8644 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02008645 if (!found)
8646 continue;
8647 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008648 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02008649 /* we have the sum of the maxconns in <total>. We only
8650 * keep 10% of that sum to set the default fullconn, with
8651 * a hard minimum of 1 (to avoid a divide by zero).
8652 */
8653 curproxy->fullconn = (total + 9) / 10;
8654 if (!curproxy->fullconn)
8655 curproxy->fullconn = 1;
8656 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01008657 }
8658
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008659 /*
8660 * Recount currently required checks.
8661 */
8662
8663 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
8664 int optnum;
8665
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008666 for (optnum = 0; cfg_opts[optnum].name; optnum++)
8667 if (curproxy->options & cfg_opts[optnum].val)
8668 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008669
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008670 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
8671 if (curproxy->options2 & cfg_opts2[optnum].val)
8672 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008673 }
8674
Willy Tarreau0fca4832015-05-01 19:12:05 +02008675 /* compute the required process bindings for the peers */
8676 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
8677 if (curproxy->table.peers.p)
8678 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
8679
Willy Tarreau122541c2011-09-07 21:24:49 +02008680 if (peers) {
8681 struct peers *curpeers = peers, **last;
8682 struct peer *p, *pb;
8683
Willy Tarreau1e273012015-05-01 19:15:17 +02008684 /* Remove all peers sections which don't have a valid listener,
8685 * which are not used by any table, or which are bound to more
8686 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02008687 */
8688 last = &peers;
8689 while (*last) {
8690 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008691
8692 if (curpeers->state == PR_STSTOPPED) {
8693 /* the "disabled" keyword was present */
8694 if (curpeers->peers_fe)
8695 stop_proxy(curpeers->peers_fe);
8696 curpeers->peers_fe = NULL;
8697 }
8698 else if (!curpeers->peers_fe) {
8699 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
8700 curpeers->id, localpeer);
8701 }
David Carliere6c39412015-07-02 07:00:17 +00008702 else if (my_popcountl(curpeers->peers_fe->bind_proc) != 1) {
Willy Tarreau1e273012015-05-01 19:15:17 +02008703 /* either it's totally stopped or too much used */
8704 if (curpeers->peers_fe->bind_proc) {
8705 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreau64c57222015-05-04 21:48:51 +02008706 "running in different processes (%d different ones). "
8707 "Check global.nbproc and all tables' bind-process "
David Carliere6c39412015-07-02 07:00:17 +00008708 "settings.\n", curpeers->id, my_popcountl(curpeers->peers_fe->bind_proc));
Willy Tarreau1e273012015-05-01 19:15:17 +02008709 cfgerr++;
8710 }
8711 stop_proxy(curpeers->peers_fe);
8712 curpeers->peers_fe = NULL;
8713 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008714 else {
Emeric Brunb3971ab2015-05-12 18:49:09 +02008715 peers_init_sync(curpeers);
Willy Tarreau122541c2011-09-07 21:24:49 +02008716 last = &curpeers->next;
8717 continue;
8718 }
8719
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008720 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02008721 p = curpeers->remote;
8722 while (p) {
8723 pb = p->next;
8724 free(p->id);
8725 free(p);
8726 p = pb;
8727 }
8728
8729 /* Destroy and unlink this curpeers section.
8730 * Note: curpeers is backed up into *last.
8731 */
8732 free(curpeers->id);
8733 curpeers = curpeers->next;
8734 free(*last);
8735 *last = curpeers;
8736 }
8737 }
8738
Willy Tarreau6866f3f2015-05-01 19:09:08 +02008739 /* initialize stick-tables on backend capable proxies. This must not
8740 * be done earlier because the data size may be discovered while parsing
8741 * other proxies.
8742 */
8743 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8744 if (curproxy->state == PR_STSTOPPED)
8745 continue;
8746
8747 if (!stktable_init(&curproxy->table)) {
8748 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
8749 cfgerr++;
8750 }
8751 }
8752
Simon Horman0d16a402015-01-30 11:22:58 +09008753 if (mailers) {
8754 struct mailers *curmailers = mailers, **last;
8755 struct mailer *m, *mb;
8756
8757 /* Remove all mailers sections which don't have a valid listener.
8758 * This can happen when a mailers section is never referenced.
8759 */
8760 last = &mailers;
8761 while (*last) {
8762 curmailers = *last;
8763 if (curmailers->users) {
8764 last = &curmailers->next;
8765 continue;
8766 }
8767
8768 Warning("Removing incomplete section 'mailers %s'.\n",
8769 curmailers->id);
8770
8771 m = curmailers->mailer_list;
8772 while (m) {
8773 mb = m->next;
8774 free(m->id);
8775 free(m);
8776 m = mb;
8777 }
8778
8779 /* Destroy and unlink this curmailers section.
8780 * Note: curmailers is backed up into *last.
8781 */
8782 free(curmailers->id);
8783 curmailers = curmailers->next;
8784 free(*last);
8785 *last = curmailers;
8786 }
8787 }
8788
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02008789 /* Update server_state_file_name to backend name if backend is supposed to use
8790 * a server-state file locally defined and none has been provided */
8791 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8792 if (curproxy->load_server_state_from_file == PR_SRV_STATE_FILE_LOCAL &&
8793 curproxy->server_state_file_name == NULL)
8794 curproxy->server_state_file_name = strdup(curproxy->id);
8795 }
8796
Willy Tarreau34eb6712011-10-24 18:15:04 +02008797 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02008798 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02008799 MEM_F_SHARED);
8800
Willy Tarreaubb925012009-07-23 13:36:36 +02008801 if (cfgerr > 0)
8802 err_code |= ERR_ALERT | ERR_FATAL;
8803 out:
8804 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02008805}
8806
Willy Tarreau5b2c3362008-07-09 19:39:06 +02008807/*
8808 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
8809 * parsing sessions.
8810 */
8811void cfg_register_keywords(struct cfg_kw_list *kwl)
8812{
8813 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
8814}
Willy Tarreaubaaee002006-06-26 02:48:02 +02008815
Willy Tarreau5b2c3362008-07-09 19:39:06 +02008816/*
8817 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
8818 */
8819void cfg_unregister_keywords(struct cfg_kw_list *kwl)
8820{
8821 LIST_DEL(&kwl->list);
8822 LIST_INIT(&kwl->list);
8823}
Willy Tarreaubaaee002006-06-26 02:48:02 +02008824
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01008825/* this function register new section in the haproxy configuration file.
8826 * <section_name> is the name of this new section and <section_parser>
8827 * is the called parser. If two section declaration have the same name,
8828 * only the first declared is used.
8829 */
8830int cfg_register_section(char *section_name,
8831 int (*section_parser)(const char *, int, char **, int))
8832{
8833 struct cfg_section *cs;
8834
8835 cs = calloc(1, sizeof(*cs));
8836 if (!cs) {
8837 Alert("register section '%s': out of memory.\n", section_name);
8838 return 0;
8839 }
8840
8841 cs->section_name = section_name;
8842 cs->section_parser = section_parser;
8843
8844 LIST_ADDQ(&sections, &cs->list);
8845
8846 return 1;
8847}
8848
Willy Tarreaubaaee002006-06-26 02:48:02 +02008849/*
8850 * Local variables:
8851 * c-indent-level: 8
8852 * c-basic-offset: 8
8853 * End:
8854 */