blob: 44070a541e9c543af83beb15c9bff63280009cc2 [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;
Dragan Dosen59cee972015-09-19 22:09:02 +02001574 logheader = realloc(logheader, global.max_syslog_len + 1);
Dragan Dosen1322d092015-09-22 16:05:32 +02001575 logheader_rfc5424 = realloc(logheader_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02001576 logline = realloc(logline, global.max_syslog_len + 1);
Dragan Dosen0b85ece2015-09-25 19:17:44 +02001577 logline_rfc5424 = realloc(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02001578 }
1579
Dragan Dosen1322d092015-09-22 16:05:32 +02001580 /* after the length, a format may be specified */
1581 if (strcmp(args[arg+2], "format") == 0) {
1582 logsrv->format = get_log_format(args[arg+3]);
1583 if (logsrv->format < 0) {
1584 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
1585 err_code |= ERR_ALERT | ERR_FATAL;
1586 goto out;
1587 }
1588
1589 /* skip these two args */
1590 arg += 2;
1591 }
1592
William Lallemand1a748ae2015-05-19 16:37:23 +02001593 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
1594 goto out;
1595
Willy Tarreau18324f52014-06-27 18:10:07 +02001596 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001597 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001598 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001599 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001600 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001601 }
1602
William Lallemand0f99e342011-10-12 17:50:54 +02001603 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02001604 if (*(args[arg+3])) {
1605 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001606 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001607 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001608 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001609 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001610 }
1611 }
1612
William Lallemand0f99e342011-10-12 17:50:54 +02001613 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02001614 if (*(args[arg+4])) {
1615 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001616 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001617 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001618 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001619 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001620 }
1621 }
1622
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02001623 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001624 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001625 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001626 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001627 free(logsrv);
1628 goto out;
1629 }
1630 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001631
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001632 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001633 if (port1 != port2) {
1634 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1635 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001636 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001637 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001638 goto out;
1639 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001640
William Lallemand0f99e342011-10-12 17:50:54 +02001641 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001642 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001643 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001644 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001645
William Lallemand0f99e342011-10-12 17:50:54 +02001646 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001647 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001648 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1649 char *name;
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001650
1651 if (global.log_send_hostname != NULL) {
1652 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1653 err_code |= ERR_ALERT;
1654 goto out;
1655 }
1656
1657 if (*(args[1]))
1658 name = args[1];
1659 else
1660 name = hostname;
1661
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001662 free(global.log_send_hostname);
Dragan Dosenc8cfa7b2015-09-28 13:28:21 +02001663 global.log_send_hostname = strdup(name);
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001664 }
Baptiste Assmann6bc89362015-08-23 09:22:25 +02001665 else if (!strcmp(args[0], "server-state-base")) { /* path base where HAProxy can find server state files */
1666 if (global.server_state_base != NULL) {
1667 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1668 err_code |= ERR_ALERT;
1669 goto out;
1670 }
1671
1672 if (!*(args[1])) {
1673 Alert("parsing [%s:%d] : '%s' expects one argument: a directory path.\n", file, linenum, args[0]);
1674 err_code |= ERR_FATAL;
1675 goto out;
1676 }
1677
1678 global.server_state_base = strdup(args[1]);
1679 }
Baptiste Assmanne0882262015-08-23 09:54:31 +02001680 else if (!strcmp(args[0], "server-state-file")) { /* path to the file where HAProxy can load the server states */
1681 if (global.server_state_file != NULL) {
1682 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1683 err_code |= ERR_ALERT;
1684 goto out;
1685 }
1686
1687 if (!*(args[1])) {
1688 Alert("parsing [%s:%d] : '%s' expect one argument: a file path.\n", file, linenum, args[0]);
1689 err_code |= ERR_FATAL;
1690 goto out;
1691 }
1692
1693 global.server_state_file = strdup(args[1]);
1694 }
Kevinm48936af2010-12-22 16:08:21 +00001695 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
William Lallemand1a748ae2015-05-19 16:37:23 +02001696 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1697 goto out;
Kevinm48936af2010-12-22 16:08:21 +00001698 if (*(args[1]) == 0) {
1699 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1700 err_code |= ERR_ALERT | ERR_FATAL;
1701 goto out;
1702 }
Dragan Dosen43885c72015-10-01 13:18:13 +02001703 chunk_destroy(&global.log_tag);
1704 chunk_initstr(&global.log_tag, strdup(args[1]));
Kevinm48936af2010-12-22 16:08:21 +00001705 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001706 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
William Lallemand1a748ae2015-05-19 16:37:23 +02001707 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1708 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001709 if (global.spread_checks != 0) {
1710 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001711 err_code |= ERR_ALERT;
1712 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001713 }
1714 if (*(args[1]) == 0) {
1715 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001716 err_code |= ERR_ALERT | ERR_FATAL;
1717 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001718 }
1719 global.spread_checks = atol(args[1]);
1720 if (global.spread_checks < 0 || global.spread_checks > 50) {
1721 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001722 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001723 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001724 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001725 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1726 const char *err;
1727 unsigned int val;
1728
William Lallemand1a748ae2015-05-19 16:37:23 +02001729 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1730 goto out;
Willy Tarreau1746eec2014-04-25 10:46:47 +02001731 if (*(args[1]) == 0) {
1732 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1733 err_code |= ERR_ALERT | ERR_FATAL;
1734 goto out;
1735 }
1736
1737 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1738 if (err) {
1739 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1740 err_code |= ERR_ALERT | ERR_FATAL;
1741 }
1742 global.max_spread_checks = val;
1743 if (global.max_spread_checks < 0) {
1744 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1745 err_code |= ERR_ALERT | ERR_FATAL;
1746 }
1747 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001748 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1749#ifdef USE_CPU_AFFINITY
1750 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001751 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001752 unsigned long cpus = 0;
1753
1754 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001755 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001756 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001757 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001758 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001759 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001760 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001761 proc = atol(args[1]);
1762 if (proc >= 1 && proc <= LONGBITS)
1763 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001764 }
1765
1766 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001767 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",
1768 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001769 err_code |= ERR_ALERT | ERR_FATAL;
1770 goto out;
1771 }
1772
1773 cur_arg = 2;
1774 while (*args[cur_arg]) {
1775 unsigned int low, high;
1776
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001777 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001778 char *dash = strchr(args[cur_arg], '-');
1779
1780 low = high = str2uic(args[cur_arg]);
1781 if (dash)
1782 high = str2uic(dash + 1);
1783
1784 if (high < low) {
1785 unsigned int swap = low;
1786 low = high;
1787 high = swap;
1788 }
1789
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001790 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001791 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001792 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001793 err_code |= ERR_ALERT | ERR_FATAL;
1794 goto out;
1795 }
1796
1797 while (low <= high)
1798 cpus |= 1UL << low++;
1799 }
1800 else {
1801 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1802 file, linenum, args[0], args[cur_arg]);
1803 err_code |= ERR_ALERT | ERR_FATAL;
1804 goto out;
1805 }
1806 cur_arg++;
1807 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001808 for (i = 0; i < LONGBITS; i++)
1809 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001810 global.cpu_map[i] = cpus;
1811#else
1812 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1813 err_code |= ERR_ALERT | ERR_FATAL;
1814 goto out;
1815#endif
1816 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001817 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001818 struct cfg_kw_list *kwl;
1819 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001820 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001821
1822 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1823 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1824 if (kwl->kw[index].section != CFG_GLOBAL)
1825 continue;
1826 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001827 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001828 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001829 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001830 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001831 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001832 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001833 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001834 err_code |= ERR_WARN;
1835 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001836 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001837 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001838 }
1839 }
1840 }
1841
Willy Tarreaubaaee002006-06-26 02:48:02 +02001842 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001843 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001844 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001845
Willy Tarreau058e9072009-07-20 09:30:05 +02001846 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001847 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001848 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001849}
1850
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001851void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001852{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001853 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001854 defproxy.mode = PR_MODE_TCP;
1855 defproxy.state = PR_STNEW;
1856 defproxy.maxconn = cfg_maxpconn;
1857 defproxy.conn_retries = CONN_RETRIES;
Joseph Lynch726ab712015-05-11 23:25:34 -07001858 defproxy.redispatch_after = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001859
Simon Horman66183002013-02-23 10:16:43 +09001860 defproxy.defsrv.check.inter = DEF_CHKINTR;
1861 defproxy.defsrv.check.fastinter = 0;
1862 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001863 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1864 defproxy.defsrv.agent.fastinter = 0;
1865 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001866 defproxy.defsrv.check.rise = DEF_RISETIME;
1867 defproxy.defsrv.check.fall = DEF_FALLTIME;
1868 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1869 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001870 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001871 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001872 defproxy.defsrv.maxqueue = 0;
1873 defproxy.defsrv.minconn = 0;
1874 defproxy.defsrv.maxconn = 0;
1875 defproxy.defsrv.slowstart = 0;
1876 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1877 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1878 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Simon Horman64e34162015-02-06 11:11:57 +09001879
1880 defproxy.email_alert.level = LOG_ALERT;
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02001881 defproxy.load_server_state_from_file = PR_SRV_STATE_FILE_UNSPEC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001882}
1883
Willy Tarreauade5ec42010-01-28 19:33:49 +01001884
Willy Tarreau63af98d2014-05-18 08:11:41 +02001885/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1886 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1887 * ERR_FATAL in case of error.
1888 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001889static int create_cond_regex_rule(const char *file, int line,
1890 struct proxy *px, int dir, int action, int flags,
1891 const char *cmd, const char *reg, const char *repl,
1892 const char **cond_start)
1893{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001894 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001895 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001896 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001897 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001898 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001899 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001900 int cs;
1901 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001902
1903 if (px == &defproxy) {
1904 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001905 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001906 goto err;
1907 }
1908
1909 if (*reg == 0) {
1910 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001911 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001912 goto err;
1913 }
1914
1915 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001916 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001917
Willy Tarreau5321c422010-01-28 20:35:13 +01001918 if (cond_start &&
1919 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001920 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1921 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1922 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001923 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001924 goto err;
1925 }
1926 }
1927 else if (cond_start && **cond_start) {
1928 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1929 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001930 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001931 goto err;
1932 }
1933
Willy Tarreau63af98d2014-05-18 08:11:41 +02001934 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001935 (dir == SMP_OPT_DIR_REQ) ?
1936 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1937 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1938 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001939
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001940 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001941 if (!preg) {
1942 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001943 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001944 goto err;
1945 }
1946
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001947 cs = !(flags & REG_ICASE);
1948 cap = !(flags & REG_NOSUB);
1949 error = NULL;
1950 if (!regex_comp(reg, preg, cs, cap, &error)) {
1951 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1952 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001953 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001954 goto err;
1955 }
1956
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001957 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001958 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001959 if (repl && err) {
1960 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1961 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001962 ret_code |= ERR_ALERT | ERR_FATAL;
1963 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001964 }
1965
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001966 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001967 ret_code |= ERR_WARN;
1968
1969 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001970
Willy Tarreau63af98d2014-05-18 08:11:41 +02001971 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001972 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001973 err:
1974 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001975 free(errmsg);
1976 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001977}
1978
Willy Tarreaubaaee002006-06-26 02:48:02 +02001979/*
William Lallemand51097192015-04-14 16:35:22 +02001980 * Parse a line in a <listen>, <frontend> or <backend> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001981 * Returns the error code, 0 if OK, or any combination of :
1982 * - ERR_ABORT: must abort ASAP
1983 * - ERR_FATAL: we can continue parsing but not start the service
1984 * - ERR_WARN: a warning has been emitted
1985 * - ERR_ALERT: an alert has been emitted
1986 * Only the two first ones can stop processing, the two others are just
1987 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001988 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001989int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1990{
1991 static struct peers *curpeers = NULL;
1992 struct peer *newpeer = NULL;
1993 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001994 struct bind_conf *bind_conf;
1995 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001996 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001997 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001998
1999 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002000 if (!*args[1]) {
2001 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01002002 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002003 goto out;
2004 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002005
William Lallemand6e62fb62015-04-28 16:55:23 +02002006 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2007 goto out;
2008
Emeric Brun32da3c42010-09-23 18:39:19 +02002009 err = invalid_char(args[1]);
2010 if (err) {
2011 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2012 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01002013 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002014 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002015 }
2016
2017 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
2018 /*
2019 * If there are two proxies with the same name only following
2020 * combinations are allowed:
2021 */
2022 if (strcmp(curpeers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002023 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 +02002024 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002025 err_code |= ERR_ALERT | ERR_FATAL;
Emeric Brun32da3c42010-09-23 18:39:19 +02002026 }
2027 }
2028
2029 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
2030 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2031 err_code |= ERR_ALERT | ERR_ABORT;
2032 goto out;
2033 }
2034
2035 curpeers->next = peers;
2036 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002037 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002038 curpeers->conf.line = linenum;
2039 curpeers->last_change = now.tv_sec;
2040 curpeers->id = strdup(args[1]);
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002041 curpeers->state = PR_STNEW;
Emeric Brun32da3c42010-09-23 18:39:19 +02002042 }
2043 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01002044 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01002045 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002046 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02002047
2048 if (!*args[2]) {
2049 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2050 file, linenum, args[0]);
2051 err_code |= ERR_ALERT | ERR_FATAL;
2052 goto out;
2053 }
2054
2055 err = invalid_char(args[1]);
2056 if (err) {
2057 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2058 file, linenum, *err, args[1]);
2059 err_code |= ERR_ALERT | ERR_FATAL;
2060 goto out;
2061 }
2062
2063 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
2064 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2065 err_code |= ERR_ALERT | ERR_ABORT;
2066 goto out;
2067 }
2068
2069 /* the peers are linked backwards first */
2070 curpeers->count++;
2071 newpeer->next = curpeers->remote;
2072 curpeers->remote = newpeer;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002073 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002074 newpeer->conf.line = linenum;
2075
2076 newpeer->last_change = now.tv_sec;
2077 newpeer->id = strdup(args[1]);
2078
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002079 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002080 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01002081 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002082 err_code |= ERR_ALERT | ERR_FATAL;
2083 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002084 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01002085
2086 proto = protocol_by_family(sk->ss_family);
2087 if (!proto || !proto->connect) {
2088 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2089 file, linenum, args[0], args[1]);
2090 err_code |= ERR_ALERT | ERR_FATAL;
2091 goto out;
2092 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002093
2094 if (port1 != port2) {
2095 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2096 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002097 err_code |= ERR_ALERT | ERR_FATAL;
2098 goto out;
2099 }
2100
Willy Tarreau2aa38802013-02-20 19:20:59 +01002101 if (!port1) {
2102 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2103 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002104 err_code |= ERR_ALERT | ERR_FATAL;
2105 goto out;
2106 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002107
Emeric Brun32da3c42010-09-23 18:39:19 +02002108 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002109 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002110 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02002111 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02002112
Emeric Brun32da3c42010-09-23 18:39:19 +02002113 if (strcmp(newpeer->id, localpeer) == 0) {
2114 /* Current is local peer, it define a frontend */
2115 newpeer->local = 1;
Emeric Brunb3971ab2015-05-12 18:49:09 +02002116 peers->local = newpeer;
Emeric Brun32da3c42010-09-23 18:39:19 +02002117
2118 if (!curpeers->peers_fe) {
2119 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
2120 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2121 err_code |= ERR_ALERT | ERR_ABORT;
2122 goto out;
2123 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002124
Willy Tarreau237250c2011-07-29 01:49:03 +02002125 init_new_proxy(curpeers->peers_fe);
2126 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02002127 curpeers->peers_fe->id = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002128 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
2129 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau91d96282015-03-13 15:47:26 +01002130 peers_setup_frontend(curpeers->peers_fe);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002131
2132 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
2133
Willy Tarreau902636f2013-03-10 19:44:48 +01002134 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
2135 if (errmsg && *errmsg) {
2136 indent_msg(&errmsg, 2);
2137 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002138 }
2139 else
2140 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
2141 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002142 err_code |= ERR_FATAL;
2143 goto out;
2144 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02002145
2146 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01002147 l->maxaccept = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002148 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
2149 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
Willy Tarreau9903f0e2015-04-04 18:50:31 +02002150 l->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02002151 l->handler = process_stream;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002152 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01002153 l->default_target = ((struct proxy *)curpeers->peers_fe)->default_target;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002154 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
2155 global.maxsock += l->maxconn;
2156 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002157 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01002158 else {
2159 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
2160 file, linenum, args[0], args[1],
2161 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
2162 err_code |= ERR_FATAL;
2163 goto out;
2164 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002165 }
2166 } /* neither "peer" nor "peers" */
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002167 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
2168 curpeers->state = PR_STSTOPPED;
2169 }
2170 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
2171 curpeers->state = PR_STNEW;
2172 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002173 else if (*args[0] != 0) {
2174 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2175 err_code |= ERR_ALERT | ERR_FATAL;
2176 goto out;
2177 }
2178
2179out:
Willy Tarreau902636f2013-03-10 19:44:48 +01002180 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02002181 return err_code;
2182}
2183
Baptiste Assmann325137d2015-04-13 23:40:55 +02002184/*
2185 * Parse a <resolvers> section.
2186 * Returns the error code, 0 if OK, or any combination of :
2187 * - ERR_ABORT: must abort ASAP
2188 * - ERR_FATAL: we can continue parsing but not start the service
2189 * - ERR_WARN: a warning has been emitted
2190 * - ERR_ALERT: an alert has been emitted
2191 * Only the two first ones can stop processing, the two others are just
2192 * indicators.
2193 */
2194int cfg_parse_resolvers(const char *file, int linenum, char **args, int kwm)
2195{
2196 static struct dns_resolvers *curr_resolvers = NULL;
2197 struct dns_nameserver *newnameserver = NULL;
2198 const char *err;
2199 int err_code = 0;
2200 char *errmsg = NULL;
2201
2202 if (strcmp(args[0], "resolvers") == 0) { /* new resolvers section */
2203 if (!*args[1]) {
2204 Alert("parsing [%s:%d] : missing name for resolvers section.\n", file, linenum);
2205 err_code |= ERR_ALERT | ERR_ABORT;
2206 goto out;
2207 }
2208
2209 err = invalid_char(args[1]);
2210 if (err) {
2211 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2212 file, linenum, *err, args[0], args[1]);
2213 err_code |= ERR_ALERT | ERR_ABORT;
2214 goto out;
2215 }
2216
2217 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
2218 /* Error if two resolvers owns the same name */
2219 if (strcmp(curr_resolvers->id, args[1]) == 0) {
2220 Alert("Parsing [%s:%d]: resolvers '%s' has same name as another resolvers (declared at %s:%d).\n",
2221 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2222 err_code |= ERR_ALERT | ERR_ABORT;
2223 }
2224 }
2225
2226 if ((curr_resolvers = (struct dns_resolvers *)calloc(1, sizeof(struct dns_resolvers))) == NULL) {
2227 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2228 err_code |= ERR_ALERT | ERR_ABORT;
2229 goto out;
2230 }
2231
2232 /* default values */
2233 LIST_ADDQ(&dns_resolvers, &curr_resolvers->list);
2234 curr_resolvers->conf.file = strdup(file);
2235 curr_resolvers->conf.line = linenum;
2236 curr_resolvers->id = strdup(args[1]);
2237 curr_resolvers->query_ids = EB_ROOT;
2238 /* default hold period for valid is 10s */
Baptiste Assmann4c5490a2015-07-14 21:42:49 +02002239 curr_resolvers->hold.valid = 10000;
2240 curr_resolvers->timeout.retry = 1000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002241 curr_resolvers->resolve_retries = 3;
2242 LIST_INIT(&curr_resolvers->nameserver_list);
2243 LIST_INIT(&curr_resolvers->curr_resolution);
2244 }
2245 else if (strcmp(args[0], "nameserver") == 0) { /* nameserver definition */
2246 struct sockaddr_storage *sk;
2247 int port1, port2;
2248 struct protocol *proto;
2249
2250 if (!*args[2]) {
2251 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2252 file, linenum, args[0]);
2253 err_code |= ERR_ALERT | ERR_FATAL;
2254 goto out;
2255 }
2256
2257 err = invalid_char(args[1]);
2258 if (err) {
2259 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2260 file, linenum, *err, args[1]);
2261 err_code |= ERR_ALERT | ERR_FATAL;
2262 goto out;
2263 }
2264
Baptiste Assmanna315c552015-11-02 22:55:49 +01002265 list_for_each_entry(newnameserver, &curr_resolvers->nameserver_list, list) {
2266 /* Error if two resolvers owns the same name */
2267 if (strcmp(newnameserver->id, args[1]) == 0) {
2268 Alert("Parsing [%s:%d]: nameserver '%s' has same name as another nameserver (declared at %s:%d).\n",
2269 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2270 err_code |= ERR_ALERT | ERR_FATAL;
2271 }
2272 }
2273
Baptiste Assmann325137d2015-04-13 23:40:55 +02002274 if ((newnameserver = (struct dns_nameserver *)calloc(1, sizeof(struct dns_nameserver))) == NULL) {
2275 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2276 err_code |= ERR_ALERT | ERR_ABORT;
2277 goto out;
2278 }
2279
2280 /* the nameservers are linked backward first */
2281 LIST_ADDQ(&curr_resolvers->nameserver_list, &newnameserver->list);
2282 curr_resolvers->count_nameservers++;
2283 newnameserver->resolvers = curr_resolvers;
2284 newnameserver->conf.file = strdup(file);
2285 newnameserver->conf.line = linenum;
2286 newnameserver->id = strdup(args[1]);
2287
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002288 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002289 if (!sk) {
2290 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2291 err_code |= ERR_ALERT | ERR_FATAL;
2292 goto out;
2293 }
2294
2295 proto = protocol_by_family(sk->ss_family);
2296 if (!proto || !proto->connect) {
2297 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2298 file, linenum, args[0], args[1]);
2299 err_code |= ERR_ALERT | ERR_FATAL;
2300 goto out;
2301 }
2302
2303 if (port1 != port2) {
2304 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2305 file, linenum, args[0], args[1], args[2]);
2306 err_code |= ERR_ALERT | ERR_FATAL;
2307 goto out;
2308 }
2309
2310 newnameserver->addr = *sk;
2311 }
2312 else if (strcmp(args[0], "hold") == 0) { /* hold periods */
2313 const char *res;
2314 unsigned int time;
2315
2316 if (!*args[2]) {
2317 Alert("parsing [%s:%d] : '%s' expects an <event> and a <time> as arguments.\n",
2318 file, linenum, args[0]);
2319 Alert("<event> can be either 'valid', 'nx', 'refused', 'timeout', or 'other'\n");
2320 err_code |= ERR_ALERT | ERR_FATAL;
2321 goto out;
2322 }
2323 res = parse_time_err(args[2], &time, TIME_UNIT_MS);
2324 if (res) {
2325 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2326 file, linenum, *res, args[0]);
2327 err_code |= ERR_ALERT | ERR_FATAL;
2328 goto out;
2329 }
2330 if (strcmp(args[1], "valid") == 0)
2331 curr_resolvers->hold.valid = time;
2332 else {
2333 Alert("parsing [%s:%d] : '%s' unknown <event>: '%s', expects 'valid'\n",
2334 file, linenum, args[0], args[1]);
2335 err_code |= ERR_ALERT | ERR_FATAL;
2336 goto out;
2337 }
2338
2339 }
2340 else if (strcmp(args[0], "resolve_retries") == 0) {
2341 if (!*args[1]) {
2342 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2343 file, linenum, args[0]);
2344 err_code |= ERR_ALERT | ERR_FATAL;
2345 goto out;
2346 }
2347 curr_resolvers->resolve_retries = atoi(args[1]);
2348 }
2349 else if (strcmp(args[0], "timeout") == 0) {
2350 const char *res;
2351 unsigned int timeout_retry;
2352
2353 if (!*args[2]) {
2354 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments.\n",
2355 file, linenum, args[0]);
2356 err_code |= ERR_ALERT | ERR_FATAL;
2357 goto out;
2358 }
2359 res = parse_time_err(args[2], &timeout_retry, TIME_UNIT_MS);
2360 if (res) {
2361 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2362 file, linenum, *res, args[0]);
2363 err_code |= ERR_ALERT | ERR_FATAL;
2364 goto out;
2365 }
2366 curr_resolvers->timeout.retry = timeout_retry;
2367 } /* neither "nameserver" nor "resolvers" */
2368 else if (*args[0] != 0) {
2369 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2370 err_code |= ERR_ALERT | ERR_FATAL;
2371 goto out;
2372 }
2373
2374 out:
2375 free(errmsg);
2376 return err_code;
2377}
Simon Horman0d16a402015-01-30 11:22:58 +09002378
2379/*
William Lallemand51097192015-04-14 16:35:22 +02002380 * Parse a line in a <listen>, <frontend> or <backend> section.
Simon Horman0d16a402015-01-30 11:22:58 +09002381 * Returns the error code, 0 if OK, or any combination of :
2382 * - ERR_ABORT: must abort ASAP
2383 * - ERR_FATAL: we can continue parsing but not start the service
2384 * - ERR_WARN: a warning has been emitted
2385 * - ERR_ALERT: an alert has been emitted
2386 * Only the two first ones can stop processing, the two others are just
2387 * indicators.
2388 */
2389int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
2390{
2391 static struct mailers *curmailers = NULL;
2392 struct mailer *newmailer = NULL;
2393 const char *err;
2394 int err_code = 0;
2395 char *errmsg = NULL;
2396
2397 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
2398 if (!*args[1]) {
2399 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
2400 err_code |= ERR_ALERT | ERR_ABORT;
2401 goto out;
2402 }
2403
2404 err = invalid_char(args[1]);
2405 if (err) {
2406 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2407 file, linenum, *err, args[0], args[1]);
2408 err_code |= ERR_ALERT | ERR_ABORT;
2409 goto out;
2410 }
2411
2412 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
2413 /*
2414 * If there are two proxies with the same name only following
2415 * combinations are allowed:
2416 */
2417 if (strcmp(curmailers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002418 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 +09002419 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002420 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman0d16a402015-01-30 11:22:58 +09002421 }
2422 }
2423
2424 if ((curmailers = (struct mailers *)calloc(1, sizeof(struct mailers))) == NULL) {
2425 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2426 err_code |= ERR_ALERT | ERR_ABORT;
2427 goto out;
2428 }
2429
2430 curmailers->next = mailers;
2431 mailers = curmailers;
2432 curmailers->conf.file = strdup(file);
2433 curmailers->conf.line = linenum;
2434 curmailers->id = strdup(args[1]);
2435 }
2436 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
2437 struct sockaddr_storage *sk;
2438 int port1, port2;
2439 struct protocol *proto;
2440
2441 if (!*args[2]) {
2442 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2443 file, linenum, args[0]);
2444 err_code |= ERR_ALERT | ERR_FATAL;
2445 goto out;
2446 }
2447
2448 err = invalid_char(args[1]);
2449 if (err) {
2450 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2451 file, linenum, *err, args[1]);
2452 err_code |= ERR_ALERT | ERR_FATAL;
2453 goto out;
2454 }
2455
2456 if ((newmailer = (struct mailer *)calloc(1, sizeof(struct mailer))) == NULL) {
2457 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2458 err_code |= ERR_ALERT | ERR_ABORT;
2459 goto out;
2460 }
2461
2462 /* the mailers are linked backwards first */
2463 curmailers->count++;
2464 newmailer->next = curmailers->mailer_list;
2465 curmailers->mailer_list = newmailer;
2466 newmailer->mailers = curmailers;
2467 newmailer->conf.file = strdup(file);
2468 newmailer->conf.line = linenum;
2469
2470 newmailer->id = strdup(args[1]);
2471
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002472 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Simon Horman0d16a402015-01-30 11:22:58 +09002473 if (!sk) {
2474 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2475 err_code |= ERR_ALERT | ERR_FATAL;
2476 goto out;
2477 }
2478
2479 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002480 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2481 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002482 file, linenum, args[0], args[1]);
2483 err_code |= ERR_ALERT | ERR_FATAL;
2484 goto out;
2485 }
2486
2487 if (port1 != port2) {
2488 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2489 file, linenum, args[0], args[1], args[2]);
2490 err_code |= ERR_ALERT | ERR_FATAL;
2491 goto out;
2492 }
2493
2494 if (!port1) {
2495 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2496 file, linenum, args[0], args[1], args[2]);
2497 err_code |= ERR_ALERT | ERR_FATAL;
2498 goto out;
2499 }
2500
2501 newmailer->addr = *sk;
2502 newmailer->proto = proto;
2503 newmailer->xprt = &raw_sock;
2504 newmailer->sock_init_arg = NULL;
2505 } /* neither "mailer" nor "mailers" */
2506 else if (*args[0] != 0) {
2507 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2508 err_code |= ERR_ALERT | ERR_FATAL;
2509 goto out;
2510 }
2511
2512out:
2513 free(errmsg);
2514 return err_code;
2515}
2516
Simon Horman9dc49962015-01-30 11:22:59 +09002517static void free_email_alert(struct proxy *p)
2518{
2519 free(p->email_alert.mailers.name);
2520 p->email_alert.mailers.name = NULL;
2521 free(p->email_alert.from);
2522 p->email_alert.from = NULL;
2523 free(p->email_alert.to);
2524 p->email_alert.to = NULL;
2525 free(p->email_alert.myhostname);
2526 p->email_alert.myhostname = NULL;
2527}
2528
Willy Tarreau3842f002009-06-14 11:39:52 +02002529int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002530{
2531 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002532 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002533 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002534 int rc;
2535 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002536 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002537 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002538 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002539 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002540 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002541
Willy Tarreau977b8e42006-12-29 14:19:17 +01002542 if (!strcmp(args[0], "listen"))
2543 rc = PR_CAP_LISTEN;
2544 else if (!strcmp(args[0], "frontend"))
2545 rc = PR_CAP_FE | PR_CAP_RS;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02002546 else if (!strcmp(args[0], "backend"))
Willy Tarreau977b8e42006-12-29 14:19:17 +01002547 rc = PR_CAP_BE | PR_CAP_RS;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002548 else
2549 rc = PR_CAP_NONE;
2550
2551 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002552 if (!*args[1]) {
2553 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
2554 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
2555 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002556 err_code |= ERR_ALERT | ERR_ABORT;
2557 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002558 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002559
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002560 err = invalid_char(args[1]);
2561 if (err) {
2562 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2563 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002564 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002565 }
2566
Willy Tarreau8f50b682015-05-26 11:45:02 +02002567 curproxy = (rc & PR_CAP_FE) ? proxy_fe_by_name(args[1]) : proxy_be_by_name(args[1]);
2568 if (curproxy) {
2569 Alert("Parsing [%s:%d]: %s '%s' has the same name as %s '%s' declared at %s:%d.\n",
2570 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2571 curproxy->id, curproxy->conf.file, curproxy->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002572 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002573 }
2574
Willy Tarreaubaaee002006-06-26 02:48:02 +02002575 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
2576 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002577 err_code |= ERR_ALERT | ERR_ABORT;
2578 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002579 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002580
Willy Tarreau97cb7802010-01-03 20:23:58 +01002581 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002582 curproxy->next = proxy;
2583 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002584 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2585 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002586 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002587 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002588 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002589 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002590
William Lallemand6e62fb62015-04-28 16:55:23 +02002591 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2592 if (curproxy->cap & PR_CAP_FE)
2593 Alert("parsing [%s:%d] : please use the 'bind' keyword for listening addresses.\n", file, linenum);
2594 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002595 }
2596
2597 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002598 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002599 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002600
Willy Tarreaubaaee002006-06-26 02:48:02 +02002601 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002602 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002603 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002604 curproxy->no_options = defproxy.no_options;
2605 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002606 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002607 curproxy->except_net = defproxy.except_net;
2608 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002609 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002610 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002611
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002612 if (defproxy.fwdfor_hdr_len) {
2613 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2614 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2615 }
2616
Willy Tarreaub86db342009-11-30 11:50:16 +01002617 if (defproxy.orgto_hdr_len) {
2618 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2619 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2620 }
2621
Mark Lamourinec2247f02012-01-04 13:02:01 -05002622 if (defproxy.server_id_hdr_len) {
2623 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2624 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2625 }
2626
Willy Tarreau977b8e42006-12-29 14:19:17 +01002627 if (curproxy->cap & PR_CAP_FE) {
2628 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002629 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002630 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002631
2632 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002633 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2634 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002635
2636 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2637 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002638
Willy Tarreau977b8e42006-12-29 14:19:17 +01002639 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002640 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002641 curproxy->fullconn = defproxy.fullconn;
2642 curproxy->conn_retries = defproxy.conn_retries;
Joseph Lynch726ab712015-05-11 23:25:34 -07002643 curproxy->redispatch_after = defproxy.redispatch_after;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002644 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002645
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002646 if (defproxy.check_req) {
2647 curproxy->check_req = calloc(1, defproxy.check_len);
2648 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2649 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002650 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002651
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002652 if (defproxy.expect_str) {
2653 curproxy->expect_str = strdup(defproxy.expect_str);
2654 if (defproxy.expect_regex) {
2655 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002656 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2657 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002658 }
2659 }
2660
Willy Tarreau67402132012-05-31 20:40:20 +02002661 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002662 if (defproxy.cookie_name)
2663 curproxy->cookie_name = strdup(defproxy.cookie_name);
2664 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002665 if (defproxy.cookie_domain)
2666 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002667
Willy Tarreau31936852010-10-06 16:59:56 +02002668 if (defproxy.cookie_maxidle)
2669 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2670
2671 if (defproxy.cookie_maxlife)
2672 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2673
Emeric Brun647caf12009-06-30 17:57:00 +02002674 if (defproxy.rdp_cookie_name)
2675 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2676 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2677
Willy Tarreau01732802007-11-01 22:48:15 +01002678 if (defproxy.url_param_name)
2679 curproxy->url_param_name = strdup(defproxy.url_param_name);
2680 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002681
Benoitaffb4812009-03-25 13:02:10 +01002682 if (defproxy.hh_name)
2683 curproxy->hh_name = strdup(defproxy.hh_name);
2684 curproxy->hh_len = defproxy.hh_len;
2685 curproxy->hh_match_domain = defproxy.hh_match_domain;
2686
Willy Tarreauef9a3602012-12-08 22:29:20 +01002687 if (defproxy.conn_src.iface_name)
2688 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2689 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002690 curproxy->conn_src.opts = defproxy.conn_src.opts;
Willy Tarreau29fbe512015-08-20 19:35:14 +02002691#if defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002692 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002693#endif
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02002694 curproxy->load_server_state_from_file = defproxy.load_server_state_from_file;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002695 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002696
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002697 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002698 if (defproxy.capture_name)
2699 curproxy->capture_name = strdup(defproxy.capture_name);
2700 curproxy->capture_namelen = defproxy.capture_namelen;
2701 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002702 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002703
Willy Tarreau977b8e42006-12-29 14:19:17 +01002704 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002705 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002706 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002707 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002708 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002709 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002710 curproxy->mon_net = defproxy.mon_net;
2711 curproxy->mon_mask = defproxy.mon_mask;
2712 if (defproxy.monitor_uri)
2713 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2714 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002715 if (defproxy.defbe.name)
2716 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002717
2718 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002719 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2720 if (curproxy->conf.logformat_string &&
2721 curproxy->conf.logformat_string != default_http_log_format &&
2722 curproxy->conf.logformat_string != default_tcp_log_format &&
2723 curproxy->conf.logformat_string != clf_http_log_format)
2724 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2725
2726 if (defproxy.conf.lfs_file) {
2727 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2728 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2729 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002730
2731 /* get either a pointer to the logformat string for RFC5424 structured-data or a copy of it */
2732 curproxy->conf.logformat_sd_string = defproxy.conf.logformat_sd_string;
2733 if (curproxy->conf.logformat_sd_string &&
2734 curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
2735 curproxy->conf.logformat_sd_string = strdup(curproxy->conf.logformat_sd_string);
2736
2737 if (defproxy.conf.lfsd_file) {
2738 curproxy->conf.lfsd_file = strdup(defproxy.conf.lfsd_file);
2739 curproxy->conf.lfsd_line = defproxy.conf.lfsd_line;
2740 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002741 }
2742
2743 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002744 curproxy->timeout.connect = defproxy.timeout.connect;
2745 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002746 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002747 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002748 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002749 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002750 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002751 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002752 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002753 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002754 }
2755
Willy Tarreaubaaee002006-06-26 02:48:02 +02002756 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002757 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002758
2759 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002760 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002761 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002762 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002763 LIST_INIT(&node->list);
2764 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2765 }
2766
Willy Tarreau62a61232013-04-12 18:13:46 +02002767 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2768 if (curproxy->conf.uniqueid_format_string)
2769 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2770
Dragan Dosen43885c72015-10-01 13:18:13 +02002771 chunk_dup(&curproxy->log_tag, &defproxy.log_tag);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002772
Willy Tarreau62a61232013-04-12 18:13:46 +02002773 if (defproxy.conf.uif_file) {
2774 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2775 curproxy->conf.uif_line = defproxy.conf.uif_line;
2776 }
William Lallemanda73203e2012-03-12 12:48:57 +01002777
2778 /* copy default header unique id */
2779 if (defproxy.header_unique_id)
2780 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2781
William Lallemand82fe75c2012-10-23 10:25:10 +02002782 /* default compression options */
2783 if (defproxy.comp != NULL) {
2784 curproxy->comp = calloc(1, sizeof(struct comp));
2785 curproxy->comp->algos = defproxy.comp->algos;
2786 curproxy->comp->types = defproxy.comp->types;
2787 }
2788
Willy Tarreaubaaee002006-06-26 02:48:02 +02002789 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002790 curproxy->conf.used_listener_id = EB_ROOT;
2791 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002792
Simon Horman98637e52014-06-20 12:30:16 +09002793 if (defproxy.check_path)
2794 curproxy->check_path = strdup(defproxy.check_path);
2795 if (defproxy.check_command)
2796 curproxy->check_command = strdup(defproxy.check_command);
2797
Simon Horman9dc49962015-01-30 11:22:59 +09002798 if (defproxy.email_alert.mailers.name)
2799 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2800 if (defproxy.email_alert.from)
2801 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2802 if (defproxy.email_alert.to)
2803 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2804 if (defproxy.email_alert.myhostname)
2805 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09002806 curproxy->email_alert.level = defproxy.email_alert.level;
Simon Horman9dc49962015-01-30 11:22:59 +09002807
Willy Tarreau93893792009-07-23 13:19:11 +02002808 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002809 }
2810 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2811 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002812 /* FIXME-20070101: we should do this too at the end of the
2813 * config parsing to free all default values.
2814 */
William Lallemand6e62fb62015-04-28 16:55:23 +02002815 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2816 err_code |= ERR_ABORT;
2817 goto out;
2818 }
2819
Willy Tarreaua534fea2008-08-03 12:19:50 +02002820 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002821 free(defproxy.check_command);
2822 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002823 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002824 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002825 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002826 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002827 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002828 free(defproxy.capture_name);
2829 free(defproxy.monitor_uri);
2830 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002831 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002832 free(defproxy.fwdfor_hdr_name);
2833 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002834 free(defproxy.orgto_hdr_name);
2835 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002836 free(defproxy.server_id_hdr_name);
2837 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002838 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002839 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002840 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002841 free(defproxy.expect_regex);
2842 defproxy.expect_regex = NULL;
2843 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002844
Willy Tarreau62a61232013-04-12 18:13:46 +02002845 if (defproxy.conf.logformat_string != default_http_log_format &&
2846 defproxy.conf.logformat_string != default_tcp_log_format &&
2847 defproxy.conf.logformat_string != clf_http_log_format)
2848 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002849
Willy Tarreau62a61232013-04-12 18:13:46 +02002850 free(defproxy.conf.uniqueid_format_string);
2851 free(defproxy.conf.lfs_file);
2852 free(defproxy.conf.uif_file);
Dragan Dosen43885c72015-10-01 13:18:13 +02002853 chunk_destroy(&defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09002854 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02002855
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002856 if (defproxy.conf.logformat_sd_string != default_rfc5424_sd_log_format)
2857 free(defproxy.conf.logformat_sd_string);
2858 free(defproxy.conf.lfsd_file);
2859
Willy Tarreaua534fea2008-08-03 12:19:50 +02002860 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002861 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002862
Willy Tarreaubaaee002006-06-26 02:48:02 +02002863 /* we cannot free uri_auth because it might already be used */
2864 init_default_instance();
2865 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002866 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2867 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002868 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002869 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002870 }
2871 else if (curproxy == NULL) {
2872 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002873 err_code |= ERR_ALERT | ERR_FATAL;
2874 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002875 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002876
2877 /* update the current file and line being parsed */
2878 curproxy->conf.args.file = curproxy->conf.file;
2879 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002880
2881 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002882 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2883 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2884 if (err_code & ERR_FATAL)
2885 goto out;
2886 }
2887 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002888 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002889 int cur_arg;
2890
Willy Tarreaubaaee002006-06-26 02:48:02 +02002891 if (curproxy == &defproxy) {
2892 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002893 err_code |= ERR_ALERT | ERR_FATAL;
2894 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002895 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002896 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002897 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002898
Willy Tarreau24709282013-03-10 21:32:12 +01002899 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002900 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002901 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002902 err_code |= ERR_ALERT | ERR_FATAL;
2903 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002904 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002905
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002906 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002907
2908 /* use default settings for unix sockets */
2909 bind_conf->ux.uid = global.unix_bind.ux.uid;
2910 bind_conf->ux.gid = global.unix_bind.ux.gid;
2911 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002912
2913 /* NOTE: the following line might create several listeners if there
2914 * are comma-separated IPs or port ranges. So all further processing
2915 * will have to be applied to all listeners created after last_listen.
2916 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002917 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2918 if (errmsg && *errmsg) {
2919 indent_msg(&errmsg, 2);
2920 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002921 }
2922 else
2923 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2924 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002925 err_code |= ERR_ALERT | ERR_FATAL;
2926 goto out;
2927 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002928
Willy Tarreau4348fad2012-09-20 16:48:07 +02002929 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2930 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002931 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002932 }
2933
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002934 cur_arg = 2;
2935 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002936 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002937 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002938 char *err;
2939
Willy Tarreau26982662012-09-12 23:17:10 +02002940 kw = bind_find_kw(args[cur_arg]);
2941 if (kw) {
2942 char *err = NULL;
2943 int code;
2944
2945 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002946 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2947 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002948 cur_arg += 1 + kw->skip ;
2949 err_code |= ERR_ALERT | ERR_FATAL;
2950 goto out;
2951 }
2952
Willy Tarreau4348fad2012-09-20 16:48:07 +02002953 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002954 err_code |= code;
2955
2956 if (code) {
2957 if (err && *err) {
2958 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002959 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002960 }
2961 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002962 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2963 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002964 if (code & ERR_FATAL) {
2965 free(err);
2966 cur_arg += 1 + kw->skip;
2967 goto out;
2968 }
2969 }
2970 free(err);
2971 cur_arg += 1 + kw->skip;
2972 continue;
2973 }
2974
Willy Tarreau8638f482012-09-18 18:01:17 +02002975 err = NULL;
2976 if (!bind_dumped) {
2977 bind_dump_kws(&err);
2978 indent_msg(&err, 4);
2979 bind_dumped = 1;
2980 }
2981
2982 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2983 file, linenum, args[0], args[1], args[cur_arg],
2984 err ? " Registered keywords :" : "", err ? err : "");
2985 free(err);
2986
Willy Tarreau93893792009-07-23 13:19:11 +02002987 err_code |= ERR_ALERT | ERR_FATAL;
2988 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002989 }
Willy Tarreau93893792009-07-23 13:19:11 +02002990 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002991 }
2992 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002993 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002994 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2995 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002996 err_code |= ERR_ALERT | ERR_FATAL;
2997 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002998 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002999 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003000 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003001
Willy Tarreaubaaee002006-06-26 02:48:02 +02003002 /* flush useless bits */
3003 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02003004 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003005 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02003006 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003007 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003008 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003009
William Lallemanddf1425a2015-04-28 20:17:49 +02003010 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3011 goto out;
3012
Willy Tarreau1c47f852006-07-09 08:22:27 +02003013 if (!*args[1]) {
3014 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
3015 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003016 err_code |= ERR_ALERT | ERR_FATAL;
3017 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003018 }
3019
Willy Tarreaua534fea2008-08-03 12:19:50 +02003020 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003021 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02003022 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003023 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02003024 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
3025
Willy Tarreau93893792009-07-23 13:19:11 +02003026 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003027 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003028 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
William Lallemanddf1425a2015-04-28 20:17:49 +02003029 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3030 goto out;
3031
Willy Tarreaubaaee002006-06-26 02:48:02 +02003032 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
3033 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
3034 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
3035 else {
3036 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003037 err_code |= ERR_ALERT | ERR_FATAL;
3038 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003039 }
3040 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003041 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003042 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003043
3044 if (curproxy == &defproxy) {
3045 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3046 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003047 err_code |= ERR_ALERT | ERR_FATAL;
3048 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003049 }
3050
William Lallemanddf1425a2015-04-28 20:17:49 +02003051 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3052 goto out;
3053
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003054 if (!*args[1]) {
3055 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3056 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003057 err_code |= ERR_ALERT | ERR_FATAL;
3058 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003059 }
3060
3061 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003062 curproxy->conf.id.key = curproxy->uuid;
Willy Tarreau0d1fdf72015-05-27 16:44:02 +02003063 curproxy->options |= PR_O_FORCED_ID;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003064
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003065 if (curproxy->uuid <= 0) {
3066 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003067 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003068 err_code |= ERR_ALERT | ERR_FATAL;
3069 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003070 }
3071
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003072 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
3073 if (node) {
3074 struct proxy *target = container_of(node, struct proxy, conf.id);
3075 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
3076 file, linenum, proxy_type_str(curproxy), curproxy->id,
3077 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
3078 err_code |= ERR_ALERT | ERR_FATAL;
3079 goto out;
3080 }
3081 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003082 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003083 else if (!strcmp(args[0], "description")) {
3084 int i, len=0;
3085 char *d;
3086
Cyril Bonté99ed3272010-01-24 23:29:44 +01003087 if (curproxy == &defproxy) {
3088 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3089 file, linenum, args[0]);
3090 err_code |= ERR_ALERT | ERR_FATAL;
3091 goto out;
3092 }
3093
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003094 if (!*args[1]) {
3095 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
3096 file, linenum, args[0]);
3097 return -1;
3098 }
3099
Willy Tarreau348acfe2014-04-14 15:00:39 +02003100 for (i = 1; *args[i]; i++)
3101 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003102
3103 d = (char *)calloc(1, len);
3104 curproxy->desc = d;
3105
Willy Tarreau348acfe2014-04-14 15:00:39 +02003106 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
3107 for (i = 2; *args[i]; i++)
3108 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003109
3110 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003111 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
William Lallemanddf1425a2015-04-28 20:17:49 +02003112 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3113 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003114 curproxy->state = PR_STSTOPPED;
3115 }
3116 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
William Lallemanddf1425a2015-04-28 20:17:49 +02003117 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3118 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003119 curproxy->state = PR_STNEW;
3120 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003121 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
3122 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003123 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003124
3125 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003126 unsigned int low, high;
3127
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003128 if (strcmp(args[cur_arg], "all") == 0) {
3129 set = 0;
3130 break;
3131 }
3132 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003133 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003134 }
3135 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003136 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003137 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01003138 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003139 char *dash = strchr(args[cur_arg], '-');
3140
3141 low = high = str2uic(args[cur_arg]);
3142 if (dash)
3143 high = str2uic(dash + 1);
3144
3145 if (high < low) {
3146 unsigned int swap = low;
3147 low = high;
3148 high = swap;
3149 }
3150
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003151 if (low < 1 || high > LONGBITS) {
3152 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
3153 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02003154 err_code |= ERR_ALERT | ERR_FATAL;
3155 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003156 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01003157 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003158 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003159 }
3160 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003161 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
3162 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003163 err_code |= ERR_ALERT | ERR_FATAL;
3164 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003165 }
3166 cur_arg++;
3167 }
3168 curproxy->bind_proc = set;
3169 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003170 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02003171 if (curproxy == &defproxy) {
3172 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003173 err_code |= ERR_ALERT | ERR_FATAL;
3174 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003175 }
3176
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003177 err = invalid_char(args[1]);
3178 if (err) {
3179 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
3180 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003181 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003182 }
3183
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01003184 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003185 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
3186 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003187 err_code |= ERR_ALERT | ERR_FATAL;
3188 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003189 }
3190 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003191 else if (!strcmp(args[0], "cookie")) { /* cookie name */
3192 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003193
Willy Tarreau977b8e42006-12-29 14:19:17 +01003194 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003195 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003196
Willy Tarreaubaaee002006-06-26 02:48:02 +02003197 if (*(args[1]) == 0) {
3198 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
3199 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003200 err_code |= ERR_ALERT | ERR_FATAL;
3201 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003202 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003203
Willy Tarreau67402132012-05-31 20:40:20 +02003204 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003205 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01003206 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003207 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003208 curproxy->cookie_name = strdup(args[1]);
3209 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003210
Willy Tarreaubaaee002006-06-26 02:48:02 +02003211 cur_arg = 2;
3212 while (*(args[cur_arg])) {
3213 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003214 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003215 }
3216 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003217 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003218 }
3219 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003220 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003221 }
3222 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003223 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003224 }
3225 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003226 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003227 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003228 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003229 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003230 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003231 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003232 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003233 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02003234 else if (!strcmp(args[cur_arg], "httponly")) {
3235 curproxy->ck_opts |= PR_CK_HTTPONLY;
3236 }
3237 else if (!strcmp(args[cur_arg], "secure")) {
3238 curproxy->ck_opts |= PR_CK_SECURE;
3239 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003240 else if (!strcmp(args[cur_arg], "domain")) {
3241 if (!*args[cur_arg + 1]) {
3242 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
3243 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003244 err_code |= ERR_ALERT | ERR_FATAL;
3245 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003246 }
3247
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003248 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003249 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003250 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
3251 " dots nor does not start with a dot."
3252 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003253 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003254 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003255 }
3256
3257 err = invalid_domainchar(args[cur_arg + 1]);
3258 if (err) {
3259 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
3260 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003261 err_code |= ERR_ALERT | ERR_FATAL;
3262 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003263 }
3264
Willy Tarreau68a897b2009-12-03 23:28:34 +01003265 if (!curproxy->cookie_domain) {
3266 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
3267 } else {
3268 /* one domain was already specified, add another one by
3269 * building the string which will be returned along with
3270 * the cookie.
3271 */
3272 char *new_ptr;
3273 int new_len = strlen(curproxy->cookie_domain) +
3274 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
3275 new_ptr = malloc(new_len);
3276 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
3277 free(curproxy->cookie_domain);
3278 curproxy->cookie_domain = new_ptr;
3279 }
Willy Tarreau31936852010-10-06 16:59:56 +02003280 cur_arg++;
3281 }
3282 else if (!strcmp(args[cur_arg], "maxidle")) {
3283 unsigned int maxidle;
3284 const char *res;
3285
3286 if (!*args[cur_arg + 1]) {
3287 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
3288 file, linenum, args[cur_arg]);
3289 err_code |= ERR_ALERT | ERR_FATAL;
3290 goto out;
3291 }
3292
3293 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
3294 if (res) {
3295 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3296 file, linenum, *res, args[cur_arg]);
3297 err_code |= ERR_ALERT | ERR_FATAL;
3298 goto out;
3299 }
3300 curproxy->cookie_maxidle = maxidle;
3301 cur_arg++;
3302 }
3303 else if (!strcmp(args[cur_arg], "maxlife")) {
3304 unsigned int maxlife;
3305 const char *res;
3306
3307 if (!*args[cur_arg + 1]) {
3308 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
3309 file, linenum, args[cur_arg]);
3310 err_code |= ERR_ALERT | ERR_FATAL;
3311 goto out;
3312 }
3313
3314 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
3315 if (res) {
3316 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3317 file, linenum, *res, args[cur_arg]);
3318 err_code |= ERR_ALERT | ERR_FATAL;
3319 goto out;
3320 }
3321 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003322 cur_arg++;
3323 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003324 else {
Willy Tarreau31936852010-10-06 16:59:56 +02003325 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 +02003326 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003327 err_code |= ERR_ALERT | ERR_FATAL;
3328 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003329 }
3330 cur_arg++;
3331 }
Willy Tarreau67402132012-05-31 20:40:20 +02003332 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003333 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
3334 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003335 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003336 }
3337
Willy Tarreau67402132012-05-31 20:40:20 +02003338 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003339 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
3340 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003341 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003342 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003343
Willy Tarreau67402132012-05-31 20:40:20 +02003344 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003345 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
3346 file, linenum);
3347 err_code |= ERR_ALERT | ERR_FATAL;
3348 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003349 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09003350 else if (!strcmp(args[0], "email-alert")) {
3351 if (*(args[1]) == 0) {
3352 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3353 file, linenum, args[0]);
3354 err_code |= ERR_ALERT | ERR_FATAL;
3355 goto out;
3356 }
3357
3358 if (!strcmp(args[1], "from")) {
3359 if (*(args[1]) == 0) {
3360 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3361 file, linenum, args[1]);
3362 err_code |= ERR_ALERT | ERR_FATAL;
3363 goto out;
3364 }
3365 free(curproxy->email_alert.from);
3366 curproxy->email_alert.from = strdup(args[2]);
3367 }
3368 else if (!strcmp(args[1], "mailers")) {
3369 if (*(args[1]) == 0) {
3370 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3371 file, linenum, args[1]);
3372 err_code |= ERR_ALERT | ERR_FATAL;
3373 goto out;
3374 }
3375 free(curproxy->email_alert.mailers.name);
3376 curproxy->email_alert.mailers.name = strdup(args[2]);
3377 }
3378 else if (!strcmp(args[1], "myhostname")) {
3379 if (*(args[1]) == 0) {
3380 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3381 file, linenum, args[1]);
3382 err_code |= ERR_ALERT | ERR_FATAL;
3383 goto out;
3384 }
3385 free(curproxy->email_alert.myhostname);
3386 curproxy->email_alert.myhostname = strdup(args[2]);
3387 }
Simon Horman64e34162015-02-06 11:11:57 +09003388 else if (!strcmp(args[1], "level")) {
3389 curproxy->email_alert.level = get_log_level(args[2]);
3390 if (curproxy->email_alert.level < 0) {
3391 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
3392 file, linenum, args[1], args[2]);
3393 err_code |= ERR_ALERT | ERR_FATAL;
3394 goto out;
3395 }
3396 }
Simon Horman9dc49962015-01-30 11:22:59 +09003397 else if (!strcmp(args[1], "to")) {
3398 if (*(args[1]) == 0) {
3399 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3400 file, linenum, args[1]);
3401 err_code |= ERR_ALERT | ERR_FATAL;
3402 goto out;
3403 }
3404 free(curproxy->email_alert.to);
3405 curproxy->email_alert.to = strdup(args[2]);
3406 }
3407 else {
3408 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
3409 file, linenum, args[1]);
3410 err_code |= ERR_ALERT | ERR_FATAL;
3411 goto out;
3412 }
Simon Horman64e34162015-02-06 11:11:57 +09003413 /* Indicate that the email_alert is at least partially configured */
3414 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09003415 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09003416 else if (!strcmp(args[0], "external-check")) {
3417 if (*(args[1]) == 0) {
3418 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3419 file, linenum, args[0]);
3420 err_code |= ERR_ALERT | ERR_FATAL;
3421 goto out;
3422 }
3423
3424 if (!strcmp(args[1], "command")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003425 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003426 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003427 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003428 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3429 file, linenum, args[1]);
3430 err_code |= ERR_ALERT | ERR_FATAL;
3431 goto out;
3432 }
3433 free(curproxy->check_command);
3434 curproxy->check_command = strdup(args[2]);
3435 }
3436 else if (!strcmp(args[1], "path")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003437 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003438 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003439 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003440 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3441 file, linenum, args[1]);
3442 err_code |= ERR_ALERT | ERR_FATAL;
3443 goto out;
3444 }
3445 free(curproxy->check_path);
3446 curproxy->check_path = strdup(args[2]);
3447 }
3448 else {
3449 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
3450 file, linenum, args[1]);
3451 err_code |= ERR_ALERT | ERR_FATAL;
3452 goto out;
3453 }
3454 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02003455 else if (!strcmp(args[0], "persist")) { /* persist */
3456 if (*(args[1]) == 0) {
3457 Alert("parsing [%s:%d] : missing persist method.\n",
3458 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003459 err_code |= ERR_ALERT | ERR_FATAL;
3460 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003461 }
3462
3463 if (!strncmp(args[1], "rdp-cookie", 10)) {
3464 curproxy->options2 |= PR_O2_RDPC_PRST;
3465
Emeric Brunb982a3d2010-01-04 15:45:53 +01003466 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003467 const char *beg, *end;
3468
3469 beg = args[1] + 11;
3470 end = strchr(beg, ')');
3471
William Lallemanddf1425a2015-04-28 20:17:49 +02003472 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3473 goto out;
3474
Emeric Brun647caf12009-06-30 17:57:00 +02003475 if (!end || end == beg) {
3476 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3477 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003478 err_code |= ERR_ALERT | ERR_FATAL;
3479 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003480 }
3481
3482 free(curproxy->rdp_cookie_name);
3483 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3484 curproxy->rdp_cookie_len = end-beg;
3485 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003486 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003487 free(curproxy->rdp_cookie_name);
3488 curproxy->rdp_cookie_name = strdup("msts");
3489 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3490 }
3491 else { /* syntax */
3492 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3493 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003494 err_code |= ERR_ALERT | ERR_FATAL;
3495 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003496 }
3497 }
3498 else {
3499 Alert("parsing [%s:%d] : unknown persist method.\n",
3500 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003501 err_code |= ERR_ALERT | ERR_FATAL;
3502 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003503 }
3504 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003505 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreau6db62c52015-08-10 19:04:29 +02003506 Alert("parsing [%s:%d] : '%s' is not supported anymore, please check the documentation.\n", file, linenum, args[0]);
3507 err_code |= ERR_ALERT | ERR_FATAL;
3508 goto out;
3509 }
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02003510 else if (!strcmp(args[0], "load-server-state-from-file")) {
3511 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3512 err_code |= ERR_WARN;
3513 if (!strcmp(args[1], "global")) { /* use the file pointed to by global server-state-file directive */
3514 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_GLOBAL;
3515 }
3516 else if (!strcmp(args[1], "local")) { /* use the server-state-file-name variable to locate the server-state file */
3517 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_LOCAL;
3518 }
3519 else if (!strcmp(args[1], "none")) { /* don't use server-state-file directive for this backend */
3520 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
3521 }
3522 else {
3523 Alert("parsing [%s:%d] : '%s' expects 'global', 'local' or 'none'. Got '%s'\n",
3524 file, linenum, args[0], args[1]);
3525 err_code |= ERR_ALERT | ERR_FATAL;
3526 goto out;
3527 }
3528 }
3529 else if (!strcmp(args[0], "server-state-file-name")) {
3530 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3531 err_code |= ERR_WARN;
3532 if (*(args[1]) == 0) {
3533 Alert("parsing [%s:%d] : '%s' expects 'use-backend-name' or a string. Got no argument\n",
3534 file, linenum, args[0]);
3535 err_code |= ERR_ALERT | ERR_FATAL;
3536 goto out;
3537 }
3538 else if (!strcmp(args[1], "use-backend-name"))
3539 curproxy->server_state_file_name = strdup(curproxy->id);
3540 else
3541 curproxy->server_state_file_name = strdup(args[1]);
3542 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003543 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003544 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003545 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003546
Willy Tarreaubaaee002006-06-26 02:48:02 +02003547 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003548 if (curproxy == &defproxy) {
3549 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3550 err_code |= ERR_ALERT | ERR_FATAL;
3551 goto out;
3552 }
3553
William Lallemand1a748ae2015-05-19 16:37:23 +02003554 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3555 goto out;
3556
Willy Tarreaubaaee002006-06-26 02:48:02 +02003557 if (*(args[4]) == 0) {
3558 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3559 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003560 err_code |= ERR_ALERT | ERR_FATAL;
3561 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003562 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003563 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003564 curproxy->capture_name = strdup(args[2]);
3565 curproxy->capture_namelen = strlen(curproxy->capture_name);
3566 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003567 curproxy->to_log |= LW_COOKIE;
3568 }
3569 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3570 struct cap_hdr *hdr;
3571
3572 if (curproxy == &defproxy) {
3573 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 +02003574 err_code |= ERR_ALERT | ERR_FATAL;
3575 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003576 }
3577
William Lallemand1a748ae2015-05-19 16:37:23 +02003578 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3579 goto out;
3580
Willy Tarreaubaaee002006-06-26 02:48:02 +02003581 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3582 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3583 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003584 err_code |= ERR_ALERT | ERR_FATAL;
3585 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003586 }
3587
3588 hdr = calloc(sizeof(struct cap_hdr), 1);
3589 hdr->next = curproxy->req_cap;
3590 hdr->name = strdup(args[3]);
3591 hdr->namelen = strlen(args[3]);
3592 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003593 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003594 hdr->index = curproxy->nb_req_cap++;
3595 curproxy->req_cap = hdr;
3596 curproxy->to_log |= LW_REQHDR;
3597 }
3598 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3599 struct cap_hdr *hdr;
3600
3601 if (curproxy == &defproxy) {
3602 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 +02003603 err_code |= ERR_ALERT | ERR_FATAL;
3604 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003605 }
3606
William Lallemand1a748ae2015-05-19 16:37:23 +02003607 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3608 goto out;
3609
Willy Tarreaubaaee002006-06-26 02:48:02 +02003610 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3611 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3612 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003613 err_code |= ERR_ALERT | ERR_FATAL;
3614 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003615 }
3616 hdr = calloc(sizeof(struct cap_hdr), 1);
3617 hdr->next = curproxy->rsp_cap;
3618 hdr->name = strdup(args[3]);
3619 hdr->namelen = strlen(args[3]);
3620 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003621 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003622 hdr->index = curproxy->nb_rsp_cap++;
3623 curproxy->rsp_cap = hdr;
3624 curproxy->to_log |= LW_RSPHDR;
3625 }
3626 else {
3627 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3628 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003629 err_code |= ERR_ALERT | ERR_FATAL;
3630 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003631 }
3632 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003633 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003634 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003635 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003636
William Lallemanddf1425a2015-04-28 20:17:49 +02003637 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3638 goto out;
3639
Willy Tarreaubaaee002006-06-26 02:48:02 +02003640 if (*(args[1]) == 0) {
3641 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3642 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003643 err_code |= ERR_ALERT | ERR_FATAL;
3644 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003645 }
3646 curproxy->conn_retries = atol(args[1]);
3647 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003648 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003649 struct act_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003650
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
Willy Tarreau20b0de52012-12-24 15:45:22 +01003657 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003658 !LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003659 (LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3660 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_DENY ||
3661 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REDIR ||
3662 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REQ_AUTH)) {
Willy Tarreau20b0de52012-12-24 15:45:22 +01003663 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 +01003664 file, linenum, args[0]);
3665 err_code |= ERR_WARN;
3666 }
3667
Willy Tarreauff011f22011-01-06 17:51:27 +01003668 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003669
Willy Tarreauff011f22011-01-06 17:51:27 +01003670 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003671 err_code |= ERR_ALERT | ERR_ABORT;
3672 goto out;
3673 }
3674
Willy Tarreau5002f572014-04-23 01:32:02 +02003675 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003676 err_code |= warnif_cond_conflicts(rule->cond,
3677 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3678 file, linenum);
3679
Willy Tarreauff011f22011-01-06 17:51:27 +01003680 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003681 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003682 else if (!strcmp(args[0], "http-response")) { /* response access control */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003683 struct act_rule *rule;
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003684
3685 if (curproxy == &defproxy) {
3686 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3687 err_code |= ERR_ALERT | ERR_FATAL;
3688 goto out;
3689 }
3690
3691 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003692 !LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003693 (LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3694 LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_DENY)) {
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003695 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3696 file, linenum, args[0]);
3697 err_code |= ERR_WARN;
3698 }
3699
3700 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3701
3702 if (!rule) {
3703 err_code |= ERR_ALERT | ERR_ABORT;
3704 goto out;
3705 }
3706
3707 err_code |= warnif_cond_conflicts(rule->cond,
3708 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3709 file, linenum);
3710
3711 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3712 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003713 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3714 /* set the header name and length into the proxy structure */
3715 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3716 err_code |= ERR_WARN;
3717
3718 if (!*args[1]) {
3719 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3720 file, linenum, args[0]);
3721 err_code |= ERR_ALERT | ERR_FATAL;
3722 goto out;
3723 }
3724
3725 /* set the desired header name */
3726 free(curproxy->server_id_hdr_name);
3727 curproxy->server_id_hdr_name = strdup(args[1]);
3728 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3729 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003730 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003731 struct act_rule *rule;
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003732
Willy Tarreaub099aca2008-10-12 17:26:37 +02003733 if (curproxy == &defproxy) {
3734 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003735 err_code |= ERR_ALERT | ERR_FATAL;
3736 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003737 }
3738
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003739 /* emulate "block" using "http-request block". Since these rules are supposed to
3740 * be processed before all http-request rules, we put them into their own list
3741 * and will insert them at the end.
3742 */
3743 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3744 if (!rule) {
3745 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003746 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003747 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003748 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3749 err_code |= warnif_cond_conflicts(rule->cond,
3750 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3751 file, linenum);
3752 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003753
3754 if (!already_warned(WARN_BLOCK_DEPRECATED))
3755 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]);
3756
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003757 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003758 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003759 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003760
Cyril Bonté99ed3272010-01-24 23:29:44 +01003761 if (curproxy == &defproxy) {
3762 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3763 err_code |= ERR_ALERT | ERR_FATAL;
3764 goto out;
3765 }
3766
Willy Tarreaube4653b2015-05-28 15:26:58 +02003767 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003768 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3769 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003770 err_code |= ERR_ALERT | ERR_FATAL;
3771 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003772 }
3773
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003774 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003775 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003776 err_code |= warnif_cond_conflicts(rule->cond,
3777 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3778 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003779 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003780 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003781 struct switching_rule *rule;
3782
Willy Tarreaub099aca2008-10-12 17:26:37 +02003783 if (curproxy == &defproxy) {
3784 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003785 err_code |= ERR_ALERT | ERR_FATAL;
3786 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003787 }
3788
Willy Tarreau55ea7572007-06-17 19:56:27 +02003789 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003790 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003791
3792 if (*(args[1]) == 0) {
3793 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003794 err_code |= ERR_ALERT | ERR_FATAL;
3795 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003796 }
3797
Willy Tarreauf51658d2014-04-23 01:21:56 +02003798 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3799 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3800 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3801 file, linenum, errmsg);
3802 err_code |= ERR_ALERT | ERR_FATAL;
3803 goto out;
3804 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003805
Willy Tarreauf51658d2014-04-23 01:21:56 +02003806 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003807 }
3808
3809 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
3810 rule->cond = cond;
3811 rule->be.name = strdup(args[1]);
3812 LIST_INIT(&rule->list);
3813 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3814 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003815 else if (strcmp(args[0], "use-server") == 0) {
3816 struct server_rule *rule;
3817
3818 if (curproxy == &defproxy) {
3819 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3820 err_code |= ERR_ALERT | ERR_FATAL;
3821 goto out;
3822 }
3823
3824 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3825 err_code |= ERR_WARN;
3826
3827 if (*(args[1]) == 0) {
3828 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3829 err_code |= ERR_ALERT | ERR_FATAL;
3830 goto out;
3831 }
3832
3833 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3834 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3835 file, linenum, args[0]);
3836 err_code |= ERR_ALERT | ERR_FATAL;
3837 goto out;
3838 }
3839
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003840 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3841 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3842 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003843 err_code |= ERR_ALERT | ERR_FATAL;
3844 goto out;
3845 }
3846
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003847 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003848
3849 rule = (struct server_rule *)calloc(1, sizeof(*rule));
3850 rule->cond = cond;
3851 rule->srv.name = strdup(args[1]);
3852 LIST_INIT(&rule->list);
3853 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3854 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3855 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003856 else if ((!strcmp(args[0], "force-persist")) ||
3857 (!strcmp(args[0], "ignore-persist"))) {
3858 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003859
3860 if (curproxy == &defproxy) {
3861 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3862 err_code |= ERR_ALERT | ERR_FATAL;
3863 goto out;
3864 }
3865
3866 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3867 err_code |= ERR_WARN;
3868
Willy Tarreauef6494c2010-01-28 17:12:36 +01003869 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003870 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3871 file, linenum, args[0]);
3872 err_code |= ERR_ALERT | ERR_FATAL;
3873 goto out;
3874 }
3875
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003876 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3877 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3878 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003879 err_code |= ERR_ALERT | ERR_FATAL;
3880 goto out;
3881 }
3882
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003883 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3884 * where force-persist is applied.
3885 */
3886 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003887
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003888 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003889 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003890 if (!strcmp(args[0], "force-persist")) {
3891 rule->type = PERSIST_TYPE_FORCE;
3892 } else {
3893 rule->type = PERSIST_TYPE_IGNORE;
3894 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003895 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003896 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003897 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003898 else if (!strcmp(args[0], "stick-table")) {
3899 int myidx = 1;
Willy Tarreaue45288c2015-05-26 10:49:46 +02003900 struct proxy *other;
3901
Willy Tarreaue2dc1fa2015-05-26 12:08:07 +02003902 other = proxy_tbl_by_name(curproxy->id);
Willy Tarreaue45288c2015-05-26 10:49:46 +02003903 if (other) {
3904 Alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
3905 file, linenum, curproxy->id, proxy_type_str(other), other->id, other->conf.file, other->conf.line);
3906 err_code |= ERR_ALERT | ERR_FATAL;
3907 goto out;
3908 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003909
Emeric Brun32da3c42010-09-23 18:39:19 +02003910 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003911 curproxy->table.type = (unsigned int)-1;
3912 while (*args[myidx]) {
3913 const char *err;
3914
3915 if (strcmp(args[myidx], "size") == 0) {
3916 myidx++;
3917 if (!*(args[myidx])) {
3918 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3919 file, linenum, args[myidx-1]);
3920 err_code |= ERR_ALERT | ERR_FATAL;
3921 goto out;
3922 }
3923 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3924 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3925 file, linenum, *err, args[myidx-1]);
3926 err_code |= ERR_ALERT | ERR_FATAL;
3927 goto out;
3928 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003929 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003930 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003931 else if (strcmp(args[myidx], "peers") == 0) {
3932 myidx++;
Godbach50523162013-12-11 19:48:57 +08003933 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003934 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3935 file, linenum, args[myidx-1]);
3936 err_code |= ERR_ALERT | ERR_FATAL;
3937 goto out;
Godbach50523162013-12-11 19:48:57 +08003938 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003939 curproxy->table.peers.name = strdup(args[myidx++]);
3940 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003941 else if (strcmp(args[myidx], "expire") == 0) {
3942 myidx++;
3943 if (!*(args[myidx])) {
3944 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3945 file, linenum, args[myidx-1]);
3946 err_code |= ERR_ALERT | ERR_FATAL;
3947 goto out;
3948 }
3949 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3950 if (err) {
3951 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3952 file, linenum, *err, args[myidx-1]);
3953 err_code |= ERR_ALERT | ERR_FATAL;
3954 goto out;
3955 }
3956 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003957 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003958 }
3959 else if (strcmp(args[myidx], "nopurge") == 0) {
3960 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003961 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003962 }
3963 else if (strcmp(args[myidx], "type") == 0) {
3964 myidx++;
3965 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3966 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3967 file, linenum, args[myidx]);
3968 err_code |= ERR_ALERT | ERR_FATAL;
3969 goto out;
3970 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003971 /* myidx already points to next arg */
3972 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003973 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003974 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003975 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003976
3977 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003978 nw = args[myidx];
3979 while (*nw) {
3980 /* the "store" keyword supports a comma-separated list */
3981 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003982 sa = NULL; /* store arg */
3983 while (*nw && *nw != ',') {
3984 if (*nw == '(') {
3985 *nw = 0;
3986 sa = ++nw;
3987 while (*nw != ')') {
3988 if (!*nw) {
3989 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3990 file, linenum, args[0], cw);
3991 err_code |= ERR_ALERT | ERR_FATAL;
3992 goto out;
3993 }
3994 nw++;
3995 }
3996 *nw = '\0';
3997 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003998 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003999 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004000 if (*nw)
4001 *nw++ = '\0';
4002 type = stktable_get_data_type(cw);
4003 if (type < 0) {
4004 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
4005 file, linenum, args[0], cw);
4006 err_code |= ERR_ALERT | ERR_FATAL;
4007 goto out;
4008 }
Willy Tarreauac782882010-06-20 10:41:54 +02004009
4010 err = stktable_alloc_data_type(&curproxy->table, type, sa);
4011 switch (err) {
4012 case PE_NONE: break;
4013 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004014 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
4015 file, linenum, args[0], cw);
4016 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02004017 break;
4018
4019 case PE_ARG_MISSING:
4020 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
4021 file, linenum, args[0], cw);
4022 err_code |= ERR_ALERT | ERR_FATAL;
4023 goto out;
4024
4025 case PE_ARG_NOT_USED:
4026 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
4027 file, linenum, args[0], cw);
4028 err_code |= ERR_ALERT | ERR_FATAL;
4029 goto out;
4030
4031 default:
4032 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
4033 file, linenum, args[0], cw);
4034 err_code |= ERR_ALERT | ERR_FATAL;
4035 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004036 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004037 }
4038 myidx++;
4039 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004040 else {
4041 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
4042 file, linenum, args[myidx]);
4043 err_code |= ERR_ALERT | ERR_FATAL;
4044 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004045 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004046 }
4047
4048 if (!curproxy->table.size) {
4049 Alert("parsing [%s:%d] : stick-table: missing size.\n",
4050 file, linenum);
4051 err_code |= ERR_ALERT | ERR_FATAL;
4052 goto out;
4053 }
4054
4055 if (curproxy->table.type == (unsigned int)-1) {
4056 Alert("parsing [%s:%d] : stick-table: missing type.\n",
4057 file, linenum);
4058 err_code |= ERR_ALERT | ERR_FATAL;
4059 goto out;
4060 }
4061 }
4062 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004063 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02004064 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004065 int myidx = 0;
4066 const char *name = NULL;
4067 int flags;
4068
4069 if (curproxy == &defproxy) {
4070 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4071 err_code |= ERR_ALERT | ERR_FATAL;
4072 goto out;
4073 }
4074
4075 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
4076 err_code |= ERR_WARN;
4077 goto out;
4078 }
4079
4080 myidx++;
4081 if ((strcmp(args[myidx], "store") == 0) ||
4082 (strcmp(args[myidx], "store-request") == 0)) {
4083 myidx++;
4084 flags = STK_IS_STORE;
4085 }
4086 else if (strcmp(args[myidx], "store-response") == 0) {
4087 myidx++;
4088 flags = STK_IS_STORE | STK_ON_RSP;
4089 }
4090 else if (strcmp(args[myidx], "match") == 0) {
4091 myidx++;
4092 flags = STK_IS_MATCH;
4093 }
4094 else if (strcmp(args[myidx], "on") == 0) {
4095 myidx++;
4096 flags = STK_IS_MATCH | STK_IS_STORE;
4097 }
4098 else {
4099 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
4100 err_code |= ERR_ALERT | ERR_FATAL;
4101 goto out;
4102 }
4103
4104 if (*(args[myidx]) == 0) {
4105 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
4106 err_code |= ERR_ALERT | ERR_FATAL;
4107 goto out;
4108 }
4109
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004110 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01004111 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004112 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01004113 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004114 err_code |= ERR_ALERT | ERR_FATAL;
4115 goto out;
4116 }
4117
4118 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01004119 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
4120 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
4121 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004122 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004123 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004124 goto out;
4125 }
4126 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01004127 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
4128 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
4129 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004130 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004131 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004132 goto out;
4133 }
4134 }
4135
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004136 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01004137 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004138
Emeric Brunb982a3d2010-01-04 15:45:53 +01004139 if (strcmp(args[myidx], "table") == 0) {
4140 myidx++;
4141 name = args[myidx++];
4142 }
4143
Willy Tarreauef6494c2010-01-28 17:12:36 +01004144 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004145 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
4146 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
4147 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004148 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004149 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004150 goto out;
4151 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004152 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01004153 else if (*(args[myidx])) {
4154 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
4155 file, linenum, args[0], args[myidx]);
4156 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004157 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01004158 goto out;
4159 }
Emeric Brun97679e72010-09-23 17:56:44 +02004160 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004161 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02004162 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004163 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01004164
Emeric Brunb982a3d2010-01-04 15:45:53 +01004165 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
4166 rule->cond = cond;
4167 rule->expr = expr;
4168 rule->flags = flags;
4169 rule->table.name = name ? strdup(name) : NULL;
4170 LIST_INIT(&rule->list);
4171 if (flags & STK_ON_RSP)
4172 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
4173 else
4174 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
4175 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004176 else if (!strcmp(args[0], "stats")) {
4177 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
4178 curproxy->uri_auth = NULL; /* we must detach from the default config */
4179
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004180 if (!*args[1]) {
4181 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02004182 } else if (!strcmp(args[1], "admin")) {
4183 struct stats_admin_rule *rule;
4184
4185 if (curproxy == &defproxy) {
4186 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
4187 err_code |= ERR_ALERT | ERR_FATAL;
4188 goto out;
4189 }
4190
4191 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4192 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4193 err_code |= ERR_ALERT | ERR_ABORT;
4194 goto out;
4195 }
4196
4197 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4198 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4199 file, linenum, args[0], args[1]);
4200 err_code |= ERR_ALERT | ERR_FATAL;
4201 goto out;
4202 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004203 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4204 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
4205 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02004206 err_code |= ERR_ALERT | ERR_FATAL;
4207 goto out;
4208 }
4209
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004210 err_code |= warnif_cond_conflicts(cond,
4211 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4212 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02004213
4214 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
4215 rule->cond = cond;
4216 LIST_INIT(&rule->list);
4217 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004218 } else if (!strcmp(args[1], "uri")) {
4219 if (*(args[2]) == 0) {
4220 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004221 err_code |= ERR_ALERT | ERR_FATAL;
4222 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004223 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
4224 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004225 err_code |= ERR_ALERT | ERR_ABORT;
4226 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004227 }
4228 } else if (!strcmp(args[1], "realm")) {
4229 if (*(args[2]) == 0) {
4230 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004231 err_code |= ERR_ALERT | ERR_FATAL;
4232 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004233 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
4234 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004235 err_code |= ERR_ALERT | ERR_ABORT;
4236 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004237 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02004238 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004239 unsigned interval;
4240
4241 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
4242 if (err) {
4243 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
4244 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004245 err_code |= ERR_ALERT | ERR_FATAL;
4246 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004247 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
4248 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004249 err_code |= ERR_ALERT | ERR_ABORT;
4250 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004251 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004252 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004253 struct act_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004254
4255 if (curproxy == &defproxy) {
4256 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4257 err_code |= ERR_ALERT | ERR_FATAL;
4258 goto out;
4259 }
4260
4261 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4262 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4263 err_code |= ERR_ALERT | ERR_ABORT;
4264 goto out;
4265 }
4266
Willy Tarreauff011f22011-01-06 17:51:27 +01004267 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004268 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct act_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004269 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
4270 file, linenum, args[0]);
4271 err_code |= ERR_WARN;
4272 }
4273
Willy Tarreauff011f22011-01-06 17:51:27 +01004274 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004275
Willy Tarreauff011f22011-01-06 17:51:27 +01004276 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004277 err_code |= ERR_ALERT | ERR_ABORT;
4278 goto out;
4279 }
4280
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004281 err_code |= warnif_cond_conflicts(rule->cond,
4282 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4283 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01004284 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004285
Willy Tarreaubaaee002006-06-26 02:48:02 +02004286 } else if (!strcmp(args[1], "auth")) {
4287 if (*(args[2]) == 0) {
4288 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004289 err_code |= ERR_ALERT | ERR_FATAL;
4290 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004291 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
4292 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004293 err_code |= ERR_ALERT | ERR_ABORT;
4294 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004295 }
4296 } else if (!strcmp(args[1], "scope")) {
4297 if (*(args[2]) == 0) {
4298 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004299 err_code |= ERR_ALERT | ERR_FATAL;
4300 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004301 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
4302 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004303 err_code |= ERR_ALERT | ERR_ABORT;
4304 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004305 }
4306 } else if (!strcmp(args[1], "enable")) {
4307 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4308 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004309 err_code |= ERR_ALERT | ERR_ABORT;
4310 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004311 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004312 } else if (!strcmp(args[1], "hide-version")) {
4313 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
4314 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004315 err_code |= ERR_ALERT | ERR_ABORT;
4316 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004317 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01004318 } else if (!strcmp(args[1], "show-legends")) {
4319 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
4320 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4321 err_code |= ERR_ALERT | ERR_ABORT;
4322 goto out;
4323 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004324 } else if (!strcmp(args[1], "show-node")) {
4325
4326 if (*args[2]) {
4327 int i;
4328 char c;
4329
4330 for (i=0; args[2][i]; i++) {
4331 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01004332 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
4333 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004334 break;
4335 }
4336
4337 if (!i || args[2][i]) {
4338 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
4339 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
4340 file, linenum, args[0], args[1]);
4341 err_code |= ERR_ALERT | ERR_FATAL;
4342 goto out;
4343 }
4344 }
4345
4346 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
4347 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4348 err_code |= ERR_ALERT | ERR_ABORT;
4349 goto out;
4350 }
4351 } else if (!strcmp(args[1], "show-desc")) {
4352 char *desc = NULL;
4353
4354 if (*args[2]) {
4355 int i, len=0;
4356 char *d;
4357
Willy Tarreau348acfe2014-04-14 15:00:39 +02004358 for (i = 2; *args[i]; i++)
4359 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004360
4361 desc = d = (char *)calloc(1, len);
4362
Willy Tarreau348acfe2014-04-14 15:00:39 +02004363 d += snprintf(d, desc + len - d, "%s", args[2]);
4364 for (i = 3; *args[i]; i++)
4365 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004366 }
4367
4368 if (!*args[2] && !global.desc)
4369 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
4370 file, linenum, args[1]);
4371 else {
4372 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
4373 free(desc);
4374 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4375 err_code |= ERR_ALERT | ERR_ABORT;
4376 goto out;
4377 }
4378 free(desc);
4379 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004380 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004381stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02004382 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 +01004383 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004384 err_code |= ERR_ALERT | ERR_FATAL;
4385 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004386 }
4387 }
4388 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004389 int optnum;
4390
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004391 if (*(args[1]) == '\0') {
4392 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
4393 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004394 err_code |= ERR_ALERT | ERR_FATAL;
4395 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004396 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01004397
4398 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
4399 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004400 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
4401 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4402 file, linenum, cfg_opts[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;
4408
Willy Tarreau93893792009-07-23 13:19:11 +02004409 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
4410 err_code |= ERR_WARN;
4411 goto out;
4412 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004413
Willy Tarreau3842f002009-06-14 11:39:52 +02004414 curproxy->no_options &= ~cfg_opts[optnum].val;
4415 curproxy->options &= ~cfg_opts[optnum].val;
4416
4417 switch (kwm) {
4418 case KWM_STD:
4419 curproxy->options |= cfg_opts[optnum].val;
4420 break;
4421 case KWM_NO:
4422 curproxy->no_options |= cfg_opts[optnum].val;
4423 break;
4424 case KWM_DEF: /* already cleared */
4425 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004426 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004427
Willy Tarreau93893792009-07-23 13:19:11 +02004428 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004429 }
4430 }
4431
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004432 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
4433 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004434 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
4435 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4436 file, linenum, cfg_opts2[optnum].name);
4437 err_code |= ERR_ALERT | ERR_FATAL;
4438 goto out;
4439 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004440 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4441 goto out;
Willy Tarreau93893792009-07-23 13:19:11 +02004442 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4443 err_code |= ERR_WARN;
4444 goto out;
4445 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004446
Willy Tarreau3842f002009-06-14 11:39:52 +02004447 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4448 curproxy->options2 &= ~cfg_opts2[optnum].val;
4449
4450 switch (kwm) {
4451 case KWM_STD:
4452 curproxy->options2 |= cfg_opts2[optnum].val;
4453 break;
4454 case KWM_NO:
4455 curproxy->no_options2 |= cfg_opts2[optnum].val;
4456 break;
4457 case KWM_DEF: /* already cleared */
4458 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004459 }
Willy Tarreau93893792009-07-23 13:19:11 +02004460 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004461 }
4462 }
4463
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004464 /* HTTP options override each other. They can be cancelled using
4465 * "no option xxx" which only switches to default mode if the mode
4466 * was this one (useful for cancelling options set in defaults
4467 * sections).
4468 */
4469 if (strcmp(args[1], "httpclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004470 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4471 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004472 if (kwm == KWM_STD) {
4473 curproxy->options &= ~PR_O_HTTP_MODE;
4474 curproxy->options |= PR_O_HTTP_PCL;
4475 goto out;
4476 }
4477 else if (kwm == KWM_NO) {
4478 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4479 curproxy->options &= ~PR_O_HTTP_MODE;
4480 goto out;
4481 }
4482 }
4483 else if (strcmp(args[1], "forceclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004484 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4485 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004486 if (kwm == KWM_STD) {
4487 curproxy->options &= ~PR_O_HTTP_MODE;
4488 curproxy->options |= PR_O_HTTP_FCL;
4489 goto out;
4490 }
4491 else if (kwm == KWM_NO) {
4492 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4493 curproxy->options &= ~PR_O_HTTP_MODE;
4494 goto out;
4495 }
4496 }
4497 else if (strcmp(args[1], "http-server-close") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004498 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4499 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004500 if (kwm == KWM_STD) {
4501 curproxy->options &= ~PR_O_HTTP_MODE;
4502 curproxy->options |= PR_O_HTTP_SCL;
4503 goto out;
4504 }
4505 else if (kwm == KWM_NO) {
4506 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4507 curproxy->options &= ~PR_O_HTTP_MODE;
4508 goto out;
4509 }
4510 }
4511 else if (strcmp(args[1], "http-keep-alive") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004512 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4513 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004514 if (kwm == KWM_STD) {
4515 curproxy->options &= ~PR_O_HTTP_MODE;
4516 curproxy->options |= PR_O_HTTP_KAL;
4517 goto out;
4518 }
4519 else if (kwm == KWM_NO) {
4520 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4521 curproxy->options &= ~PR_O_HTTP_MODE;
4522 goto out;
4523 }
4524 }
4525 else if (strcmp(args[1], "http-tunnel") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004526 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4527 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004528 if (kwm == KWM_STD) {
4529 curproxy->options &= ~PR_O_HTTP_MODE;
4530 curproxy->options |= PR_O_HTTP_TUN;
4531 goto out;
4532 }
4533 else if (kwm == KWM_NO) {
4534 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4535 curproxy->options &= ~PR_O_HTTP_MODE;
4536 goto out;
4537 }
4538 }
4539
Joseph Lynch726ab712015-05-11 23:25:34 -07004540 /* Redispatch can take an integer argument that control when the
4541 * resispatch occurs. All values are relative to the retries option.
4542 * This can be cancelled using "no option xxx".
4543 */
4544 if (strcmp(args[1], "redispatch") == 0) {
4545 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
4546 err_code |= ERR_WARN;
4547 goto out;
4548 }
4549
4550 curproxy->no_options &= ~PR_O_REDISP;
4551 curproxy->options &= ~PR_O_REDISP;
4552
4553 switch (kwm) {
4554 case KWM_STD:
4555 curproxy->options |= PR_O_REDISP;
4556 curproxy->redispatch_after = -1;
4557 if(*args[2]) {
4558 curproxy->redispatch_after = atol(args[2]);
4559 }
4560 break;
4561 case KWM_NO:
4562 curproxy->no_options |= PR_O_REDISP;
4563 curproxy->redispatch_after = 0;
4564 break;
4565 case KWM_DEF: /* already cleared */
4566 break;
4567 }
4568 goto out;
4569 }
4570
Willy Tarreau3842f002009-06-14 11:39:52 +02004571 if (kwm != KWM_STD) {
4572 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004573 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004574 err_code |= ERR_ALERT | ERR_FATAL;
4575 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004576 }
4577
Emeric Brun3a058f32009-06-30 18:26:00 +02004578 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004579 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004580 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004581 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004582 if (*(args[2]) != '\0') {
4583 if (!strcmp(args[2], "clf")) {
4584 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004585 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004586 } else {
William Lallemand77063bc2015-05-28 18:02:48 +02004587 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004588 err_code |= ERR_ALERT | ERR_FATAL;
4589 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004590 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004591 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
4592 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004593 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004594 if (curproxy->conf.logformat_string != default_http_log_format &&
4595 curproxy->conf.logformat_string != default_tcp_log_format &&
4596 curproxy->conf.logformat_string != clf_http_log_format)
4597 free(curproxy->conf.logformat_string);
4598 curproxy->conf.logformat_string = logformat;
4599
4600 free(curproxy->conf.lfs_file);
4601 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4602 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004603 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004604 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004605 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004606 if (curproxy->conf.logformat_string != default_http_log_format &&
4607 curproxy->conf.logformat_string != default_tcp_log_format &&
4608 curproxy->conf.logformat_string != clf_http_log_format)
4609 free(curproxy->conf.logformat_string);
4610 curproxy->conf.logformat_string = default_tcp_log_format;
4611
4612 free(curproxy->conf.lfs_file);
4613 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4614 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemanddf1425a2015-04-28 20:17:49 +02004615
4616 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4617 goto out;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004618 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004619 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004620 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004621 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004622 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004623
William Lallemanddf1425a2015-04-28 20:17:49 +02004624 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4625 goto out;
4626
Willy Tarreau13943ab2006-12-31 00:24:10 +01004627 if (curproxy->cap & PR_CAP_FE)
4628 curproxy->options |= PR_O_TCP_CLI_KA;
4629 if (curproxy->cap & PR_CAP_BE)
4630 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004631 }
4632 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004633 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004634 err_code |= ERR_WARN;
4635
Willy Tarreaubaaee002006-06-26 02:48:02 +02004636 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004637 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004638 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004639 curproxy->options2 &= ~PR_O2_CHK_ANY;
4640 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004641 if (!*args[2]) { /* no argument */
4642 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4643 curproxy->check_len = strlen(DEF_CHECK_REQ);
4644 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004645 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004646 curproxy->check_req = (char *)malloc(reqlen);
4647 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004648 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004649 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004650 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004651 if (*args[4])
4652 reqlen += strlen(args[4]);
4653 else
4654 reqlen += strlen("HTTP/1.0");
4655
4656 curproxy->check_req = (char *)malloc(reqlen);
4657 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004658 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004659 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004660 if (alertif_too_many_args_idx(3, 1, file, linenum, args, &err_code))
4661 goto out;
Willy Tarreauf3c69202006-07-09 16:42:34 +02004662 }
4663 else if (!strcmp(args[1], "ssl-hello-chk")) {
4664 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004665 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004666 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004667
Willy Tarreaua534fea2008-08-03 12:19:50 +02004668 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004669 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004670 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004671 curproxy->options2 |= PR_O2_SSL3_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004672
4673 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4674 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004675 }
Willy Tarreau23677902007-05-08 23:50:35 +02004676 else if (!strcmp(args[1], "smtpchk")) {
4677 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004678 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004679 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004680 curproxy->options2 &= ~PR_O2_CHK_ANY;
4681 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004682
4683 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4684 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4685 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4686 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4687 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4688 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
4689 curproxy->check_req = (char *)malloc(reqlen);
4690 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4691 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4692 } else {
4693 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4694 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4695 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4696 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4697 }
4698 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004699 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4700 goto out;
Willy Tarreau23677902007-05-08 23:50:35 +02004701 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004702 else if (!strcmp(args[1], "pgsql-check")) {
4703 /* use PostgreSQL request to check servers' health */
4704 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4705 err_code |= ERR_WARN;
4706
4707 free(curproxy->check_req);
4708 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004709 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004710 curproxy->options2 |= PR_O2_PGSQL_CHK;
4711
4712 if (*(args[2])) {
4713 int cur_arg = 2;
4714
4715 while (*(args[cur_arg])) {
4716 if (strcmp(args[cur_arg], "user") == 0) {
4717 char * packet;
4718 uint32_t packet_len;
4719 uint32_t pv;
4720
4721 /* suboption header - needs additional argument for it */
4722 if (*(args[cur_arg+1]) == 0) {
4723 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4724 file, linenum, args[0], args[1], args[cur_arg]);
4725 err_code |= ERR_ALERT | ERR_FATAL;
4726 goto out;
4727 }
4728
4729 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4730 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4731 pv = htonl(0x30000); /* protocol version 3.0 */
4732
4733 packet = (char*) calloc(1, packet_len);
4734
4735 memcpy(packet + 4, &pv, 4);
4736
4737 /* copy "user" */
4738 memcpy(packet + 8, "user", 4);
4739
4740 /* copy username */
4741 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4742
4743 free(curproxy->check_req);
4744 curproxy->check_req = packet;
4745 curproxy->check_len = packet_len;
4746
4747 packet_len = htonl(packet_len);
4748 memcpy(packet, &packet_len, 4);
4749 cur_arg += 2;
4750 } else {
4751 /* unknown suboption - catchall */
4752 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4753 file, linenum, args[0], args[1]);
4754 err_code |= ERR_ALERT | ERR_FATAL;
4755 goto out;
4756 }
4757 } /* end while loop */
4758 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004759 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4760 goto out;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004761 }
4762
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004763 else if (!strcmp(args[1], "redis-check")) {
4764 /* use REDIS PING request to check servers' health */
4765 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4766 err_code |= ERR_WARN;
4767
4768 free(curproxy->check_req);
4769 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004770 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004771 curproxy->options2 |= PR_O2_REDIS_CHK;
4772
4773 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
4774 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4775 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004776
4777 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4778 goto out;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004779 }
4780
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004781 else if (!strcmp(args[1], "mysql-check")) {
4782 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004783 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4784 err_code |= ERR_WARN;
4785
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004786 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004787 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004788 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004789 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004790
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004791 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004792 * const char mysql40_client_auth_pkt[] = {
4793 * "\x0e\x00\x00" // packet length
4794 * "\x01" // packet number
4795 * "\x00\x00" // client capabilities
4796 * "\x00\x00\x01" // max packet
4797 * "haproxy\x00" // username (null terminated string)
4798 * "\x00" // filler (always 0x00)
4799 * "\x01\x00\x00" // packet length
4800 * "\x00" // packet number
4801 * "\x01" // COM_QUIT command
4802 * };
4803 */
4804
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004805 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4806 * const char mysql41_client_auth_pkt[] = {
4807 * "\x0e\x00\x00\" // packet length
4808 * "\x01" // packet number
4809 * "\x00\x00\x00\x00" // client capabilities
4810 * "\x00\x00\x00\x01" // max packet
4811 * "\x21" // character set (UTF-8)
4812 * char[23] // All zeroes
4813 * "haproxy\x00" // username (null terminated string)
4814 * "\x00" // filler (always 0x00)
4815 * "\x01\x00\x00" // packet length
4816 * "\x00" // packet number
4817 * "\x01" // COM_QUIT command
4818 * };
4819 */
4820
4821
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004822 if (*(args[2])) {
4823 int cur_arg = 2;
4824
4825 while (*(args[cur_arg])) {
4826 if (strcmp(args[cur_arg], "user") == 0) {
4827 char *mysqluser;
4828 int packetlen, reqlen, userlen;
4829
4830 /* suboption header - needs additional argument for it */
4831 if (*(args[cur_arg+1]) == 0) {
4832 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4833 file, linenum, args[0], args[1], args[cur_arg]);
4834 err_code |= ERR_ALERT | ERR_FATAL;
4835 goto out;
4836 }
4837 mysqluser = args[cur_arg + 1];
4838 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004839
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004840 if (*(args[cur_arg+2])) {
4841 if (!strcmp(args[cur_arg+2], "post-41")) {
4842 packetlen = userlen + 7 + 27;
4843 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004844
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004845 free(curproxy->check_req);
4846 curproxy->check_req = (char *)calloc(1, reqlen);
4847 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004848
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004849 snprintf(curproxy->check_req, 4, "%c%c%c",
4850 ((unsigned char) packetlen & 0xff),
4851 ((unsigned char) (packetlen >> 8) & 0xff),
4852 ((unsigned char) (packetlen >> 16) & 0xff));
4853
4854 curproxy->check_req[3] = 1;
4855 curproxy->check_req[5] = 130;
4856 curproxy->check_req[11] = 1;
4857 curproxy->check_req[12] = 33;
4858 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4859 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4860 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4861 cur_arg += 3;
4862 } else {
4863 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4864 err_code |= ERR_ALERT | ERR_FATAL;
4865 goto out;
4866 }
4867 } else {
4868 packetlen = userlen + 7;
4869 reqlen = packetlen + 9;
4870
4871 free(curproxy->check_req);
4872 curproxy->check_req = (char *)calloc(1, reqlen);
4873 curproxy->check_len = reqlen;
4874
4875 snprintf(curproxy->check_req, 4, "%c%c%c",
4876 ((unsigned char) packetlen & 0xff),
4877 ((unsigned char) (packetlen >> 8) & 0xff),
4878 ((unsigned char) (packetlen >> 16) & 0xff));
4879
4880 curproxy->check_req[3] = 1;
4881 curproxy->check_req[5] = 128;
4882 curproxy->check_req[8] = 1;
4883 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4884 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4885 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4886 cur_arg += 2;
4887 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004888 } else {
4889 /* unknown suboption - catchall */
4890 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4891 file, linenum, args[0], args[1]);
4892 err_code |= ERR_ALERT | ERR_FATAL;
4893 goto out;
4894 }
4895 } /* end while loop */
4896 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004897 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004898 else if (!strcmp(args[1], "ldap-check")) {
4899 /* use LDAP request to check servers' health */
4900 free(curproxy->check_req);
4901 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004902 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004903 curproxy->options2 |= PR_O2_LDAP_CHK;
4904
4905 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
4906 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
4907 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004908 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4909 goto out;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004910 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004911 else if (!strcmp(args[1], "tcp-check")) {
4912 /* use raw TCPCHK send/expect to check servers' health */
4913 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4914 err_code |= ERR_WARN;
4915
4916 free(curproxy->check_req);
4917 curproxy->check_req = NULL;
4918 curproxy->options2 &= ~PR_O2_CHK_ANY;
4919 curproxy->options2 |= PR_O2_TCPCHK_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004920 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4921 goto out;
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004922 }
Simon Horman98637e52014-06-20 12:30:16 +09004923 else if (!strcmp(args[1], "external-check")) {
4924 /* excute an external command to check servers' health */
4925 free(curproxy->check_req);
4926 curproxy->check_req = NULL;
4927 curproxy->options2 &= ~PR_O2_CHK_ANY;
4928 curproxy->options2 |= PR_O2_EXT_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004929 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4930 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09004931 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004932 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004933 int cur_arg;
4934
4935 /* insert x-forwarded-for field, but not for the IP address listed as an except.
4936 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004937 */
Ross Westaf72a1d2008-08-03 10:51:45 +02004938
Willy Tarreau87cf5142011-08-19 22:57:24 +02004939 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02004940
4941 free(curproxy->fwdfor_hdr_name);
4942 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
4943 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
4944
4945 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
4946 cur_arg = 2;
4947 while (*(args[cur_arg])) {
4948 if (!strcmp(args[cur_arg], "except")) {
4949 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004950 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004951 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4952 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004953 err_code |= ERR_ALERT | ERR_FATAL;
4954 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004955 }
4956 /* flush useless bits */
4957 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02004958 cur_arg += 2;
4959 } else if (!strcmp(args[cur_arg], "header")) {
4960 /* suboption header - needs additional argument for it */
4961 if (*(args[cur_arg+1]) == 0) {
4962 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4963 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004964 err_code |= ERR_ALERT | ERR_FATAL;
4965 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02004966 }
4967 free(curproxy->fwdfor_hdr_name);
4968 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
4969 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
4970 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02004971 } else if (!strcmp(args[cur_arg], "if-none")) {
4972 curproxy->options &= ~PR_O_FF_ALWAYS;
4973 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004974 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02004975 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02004976 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02004977 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004978 err_code |= ERR_ALERT | ERR_FATAL;
4979 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004980 }
Ross Westaf72a1d2008-08-03 10:51:45 +02004981 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004982 }
Maik Broemme2850cb42009-04-17 18:53:21 +02004983 else if (!strcmp(args[1], "originalto")) {
4984 int cur_arg;
4985
4986 /* insert x-original-to field, but not for the IP address listed as an except.
4987 * set default options (ie: bitfield, header name, etc)
4988 */
4989
4990 curproxy->options |= PR_O_ORGTO;
4991
4992 free(curproxy->orgto_hdr_name);
4993 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
4994 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
4995
Willy Tarreau87cf5142011-08-19 22:57:24 +02004996 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02004997 cur_arg = 2;
4998 while (*(args[cur_arg])) {
4999 if (!strcmp(args[cur_arg], "except")) {
5000 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005001 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 +02005002 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5003 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005004 err_code |= ERR_ALERT | ERR_FATAL;
5005 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005006 }
5007 /* flush useless bits */
5008 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
5009 cur_arg += 2;
5010 } else if (!strcmp(args[cur_arg], "header")) {
5011 /* suboption header - needs additional argument for it */
5012 if (*(args[cur_arg+1]) == 0) {
5013 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5014 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005015 err_code |= ERR_ALERT | ERR_FATAL;
5016 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005017 }
5018 free(curproxy->orgto_hdr_name);
5019 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
5020 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
5021 cur_arg += 2;
5022 } else {
5023 /* unknown suboption - catchall */
5024 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
5025 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005026 err_code |= ERR_ALERT | ERR_FATAL;
5027 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005028 }
5029 } /* end while loop */
5030 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005031 else {
5032 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005033 err_code |= ERR_ALERT | ERR_FATAL;
5034 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005035 }
Willy Tarreau93893792009-07-23 13:19:11 +02005036 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005037 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005038 else if (!strcmp(args[0], "default_backend")) {
5039 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005040 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005041
5042 if (*(args[1]) == 0) {
5043 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005044 err_code |= ERR_ALERT | ERR_FATAL;
5045 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005046 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005047 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005048 curproxy->defbe.name = strdup(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005049
5050 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5051 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005052 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005053 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01005054 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005055 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005056
Willy Tarreaua3c504c2014-04-28 22:37:32 +02005057 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
5058 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 +01005059 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005060 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005061 /* enable reconnections to dispatch */
5062 curproxy->options |= PR_O_REDISP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005063
5064 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5065 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005066 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005067 else if (!strcmp(args[0], "http-reuse")) {
5068 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5069 err_code |= ERR_WARN;
5070
5071 if (strcmp(args[1], "never") == 0) {
5072 /* enable a graceful server shutdown on an HTTP 404 response */
5073 curproxy->options &= ~PR_O_REUSE_MASK;
5074 curproxy->options |= PR_O_REUSE_NEVR;
5075 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5076 goto out;
5077 }
Willy Tarreau161d45f2015-08-05 16:02:46 +02005078 else if (strcmp(args[1], "safe") == 0) {
5079 /* enable a graceful server shutdown on an HTTP 404 response */
5080 curproxy->options &= ~PR_O_REUSE_MASK;
5081 curproxy->options |= PR_O_REUSE_SAFE;
5082 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5083 goto out;
5084 }
Willy Tarreau449d74a2015-08-05 17:16:33 +02005085 else if (strcmp(args[1], "aggressive") == 0) {
5086 curproxy->options &= ~PR_O_REUSE_MASK;
5087 curproxy->options |= PR_O_REUSE_AGGR;
5088 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5089 goto out;
5090 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005091 else if (strcmp(args[1], "always") == 0) {
5092 /* enable a graceful server shutdown on an HTTP 404 response */
5093 curproxy->options &= ~PR_O_REUSE_MASK;
5094 curproxy->options |= PR_O_REUSE_ALWS;
5095 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5096 goto out;
5097 }
5098 else {
Willy Tarreau449d74a2015-08-05 17:16:33 +02005099 Alert("parsing [%s:%d] : '%s' only supports 'never', 'safe', 'aggressive', 'always'.\n", file, linenum, args[0]);
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005100 err_code |= ERR_ALERT | ERR_FATAL;
5101 goto out;
5102 }
5103 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005104 else if (!strcmp(args[0], "http-check")) {
5105 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005106 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01005107
5108 if (strcmp(args[1], "disable-on-404") == 0) {
5109 /* enable a graceful server shutdown on an HTTP 404 response */
5110 curproxy->options |= PR_O_DISABLE404;
William Lallemanddf1425a2015-04-28 20:17:49 +02005111 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5112 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005113 }
Willy Tarreauef781042010-01-27 11:53:01 +01005114 else if (strcmp(args[1], "send-state") == 0) {
5115 /* enable emission of the apparent state of a server in HTTP checks */
5116 curproxy->options2 |= PR_O2_CHK_SNDST;
William Lallemanddf1425a2015-04-28 20:17:49 +02005117 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5118 goto out;
Willy Tarreauef781042010-01-27 11:53:01 +01005119 }
Willy Tarreaubd741542010-03-16 18:46:54 +01005120 else if (strcmp(args[1], "expect") == 0) {
5121 const char *ptr_arg;
5122 int cur_arg;
5123
5124 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5125 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5126 err_code |= ERR_ALERT | ERR_FATAL;
5127 goto out;
5128 }
5129
5130 cur_arg = 2;
5131 /* consider exclamation marks, sole or at the beginning of a word */
5132 while (*(ptr_arg = args[cur_arg])) {
5133 while (*ptr_arg == '!') {
5134 curproxy->options2 ^= PR_O2_EXP_INV;
5135 ptr_arg++;
5136 }
5137 if (*ptr_arg)
5138 break;
5139 cur_arg++;
5140 }
5141 /* now ptr_arg points to the beginning of a word past any possible
5142 * exclamation mark, and cur_arg is the argument which holds this word.
5143 */
5144 if (strcmp(ptr_arg, "status") == 0) {
5145 if (!*(args[cur_arg + 1])) {
5146 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5147 file, linenum, args[0], args[1], ptr_arg);
5148 err_code |= ERR_ALERT | ERR_FATAL;
5149 goto out;
5150 }
5151 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005152 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005153 curproxy->expect_str = strdup(args[cur_arg + 1]);
5154 }
5155 else if (strcmp(ptr_arg, "string") == 0) {
5156 if (!*(args[cur_arg + 1])) {
5157 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5158 file, linenum, args[0], args[1], ptr_arg);
5159 err_code |= ERR_ALERT | ERR_FATAL;
5160 goto out;
5161 }
5162 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005163 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005164 curproxy->expect_str = strdup(args[cur_arg + 1]);
5165 }
5166 else if (strcmp(ptr_arg, "rstatus") == 0) {
5167 if (!*(args[cur_arg + 1])) {
5168 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5169 file, linenum, args[0], args[1], ptr_arg);
5170 err_code |= ERR_ALERT | ERR_FATAL;
5171 goto out;
5172 }
5173 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005174 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005175 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005176 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005177 free(curproxy->expect_regex);
5178 curproxy->expect_regex = NULL;
5179 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005180 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005181 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5182 error = NULL;
5183 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5184 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5185 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5186 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005187 err_code |= ERR_ALERT | ERR_FATAL;
5188 goto out;
5189 }
5190 }
5191 else if (strcmp(ptr_arg, "rstring") == 0) {
5192 if (!*(args[cur_arg + 1])) {
5193 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5194 file, linenum, args[0], args[1], ptr_arg);
5195 err_code |= ERR_ALERT | ERR_FATAL;
5196 goto out;
5197 }
5198 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005199 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005200 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005201 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005202 free(curproxy->expect_regex);
5203 curproxy->expect_regex = NULL;
5204 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005205 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005206 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5207 error = NULL;
5208 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5209 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5210 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5211 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005212 err_code |= ERR_ALERT | ERR_FATAL;
5213 goto out;
5214 }
5215 }
5216 else {
5217 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
5218 file, linenum, args[0], args[1], ptr_arg);
5219 err_code |= ERR_ALERT | ERR_FATAL;
5220 goto out;
5221 }
5222 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005223 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005224 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 +02005225 err_code |= ERR_ALERT | ERR_FATAL;
5226 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005227 }
5228 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005229 else if (!strcmp(args[0], "tcp-check")) {
5230 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5231 err_code |= ERR_WARN;
5232
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005233 if (strcmp(args[1], "comment") == 0) {
5234 int cur_arg;
5235 struct tcpcheck_rule *tcpcheck;
5236
5237 cur_arg = 1;
5238 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5239 tcpcheck->action = TCPCHK_ACT_COMMENT;
5240
5241 if (!*args[cur_arg + 1]) {
5242 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5243 file, linenum, args[cur_arg]);
5244 err_code |= ERR_ALERT | ERR_FATAL;
5245 goto out;
5246 }
5247
5248 tcpcheck->comment = strdup(args[cur_arg + 1]);
5249
5250 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
William Lallemanddf1425a2015-04-28 20:17:49 +02005251 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
5252 goto out;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005253 }
5254 else if (strcmp(args[1], "connect") == 0) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005255 const char *ptr_arg;
5256 int cur_arg;
5257 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005258
5259 /* check if first rule is also a 'connect' action */
Willy Tarreau5581c272015-05-13 12:24:53 +02005260 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
5261 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
5262 tcpcheck->action == TCPCHK_ACT_COMMENT) {
5263 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
5264 }
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005265
Willy Tarreau5581c272015-05-13 12:24:53 +02005266 if (&tcpcheck->list != &curproxy->tcpcheck_rules
5267 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
5268 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
5269 file, linenum);
5270 err_code |= ERR_ALERT | ERR_FATAL;
5271 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005272 }
5273
5274 cur_arg = 2;
5275 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5276 tcpcheck->action = TCPCHK_ACT_CONNECT;
5277
5278 /* parsing each parameters to fill up the rule */
5279 while (*(ptr_arg = args[cur_arg])) {
5280 /* tcp port */
5281 if (strcmp(args[cur_arg], "port") == 0) {
5282 if ( (atol(args[cur_arg + 1]) > 65535) ||
5283 (atol(args[cur_arg + 1]) < 1) ){
5284 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
5285 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
5286 err_code |= ERR_ALERT | ERR_FATAL;
5287 goto out;
5288 }
5289 tcpcheck->port = atol(args[cur_arg + 1]);
5290 cur_arg += 2;
5291 }
5292 /* send proxy protocol */
5293 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
5294 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
5295 cur_arg++;
5296 }
5297#ifdef USE_OPENSSL
5298 else if (strcmp(args[cur_arg], "ssl") == 0) {
5299 curproxy->options |= PR_O_TCPCHK_SSL;
5300 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
5301 cur_arg++;
5302 }
5303#endif /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005304 /* comment for this tcpcheck line */
5305 else if (strcmp(args[cur_arg], "comment") == 0) {
5306 if (!*args[cur_arg + 1]) {
5307 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5308 file, linenum, args[cur_arg]);
5309 err_code |= ERR_ALERT | ERR_FATAL;
5310 goto out;
5311 }
5312 tcpcheck->comment = strdup(args[cur_arg + 1]);
5313 cur_arg += 2;
5314 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005315 else {
5316#ifdef USE_OPENSSL
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005317 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 +01005318#else /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005319 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 +01005320#endif /* USE_OPENSSL */
5321 file, linenum, args[0], args[1], args[cur_arg]);
5322 err_code |= ERR_ALERT | ERR_FATAL;
5323 goto out;
5324 }
5325
5326 }
5327
5328 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5329 }
5330 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005331 if (! *(args[2]) ) {
5332 /* SEND string expected */
5333 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
5334 file, linenum, args[0], args[1], args[2]);
5335 err_code |= ERR_ALERT | ERR_FATAL;
5336 goto out;
5337 } else {
5338 struct tcpcheck_rule *tcpcheck;
5339
5340 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5341
5342 tcpcheck->action = TCPCHK_ACT_SEND;
5343 tcpcheck->string_len = strlen(args[2]);
5344 tcpcheck->string = strdup(args[2]);
5345 tcpcheck->expect_regex = NULL;
5346
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005347 /* comment for this tcpcheck line */
5348 if (strcmp(args[3], "comment") == 0) {
5349 if (!*args[4]) {
5350 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5351 file, linenum, args[3]);
5352 err_code |= ERR_ALERT | ERR_FATAL;
5353 goto out;
5354 }
5355 tcpcheck->comment = strdup(args[4]);
5356 }
5357
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005358 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5359 }
5360 }
5361 else if (strcmp(args[1], "send-binary") == 0) {
5362 if (! *(args[2]) ) {
5363 /* SEND binary string expected */
5364 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
5365 file, linenum, args[0], args[1], args[2]);
5366 err_code |= ERR_ALERT | ERR_FATAL;
5367 goto out;
5368 } else {
5369 struct tcpcheck_rule *tcpcheck;
5370 char *err = NULL;
5371
5372 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5373
5374 tcpcheck->action = TCPCHK_ACT_SEND;
5375 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5376 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5377 file, linenum, args[0], args[1], args[2], err);
5378 err_code |= ERR_ALERT | ERR_FATAL;
5379 goto out;
5380 }
5381 tcpcheck->expect_regex = NULL;
5382
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005383 /* comment for this tcpcheck line */
5384 if (strcmp(args[3], "comment") == 0) {
5385 if (!*args[4]) {
5386 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5387 file, linenum, args[3]);
5388 err_code |= ERR_ALERT | ERR_FATAL;
5389 goto out;
5390 }
5391 tcpcheck->comment = strdup(args[4]);
5392 }
5393
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005394 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5395 }
5396 }
5397 else if (strcmp(args[1], "expect") == 0) {
5398 const char *ptr_arg;
5399 int cur_arg;
5400 int inverse = 0;
5401
5402 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5403 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5404 err_code |= ERR_ALERT | ERR_FATAL;
5405 goto out;
5406 }
5407
5408 cur_arg = 2;
5409 /* consider exclamation marks, sole or at the beginning of a word */
5410 while (*(ptr_arg = args[cur_arg])) {
5411 while (*ptr_arg == '!') {
5412 inverse = !inverse;
5413 ptr_arg++;
5414 }
5415 if (*ptr_arg)
5416 break;
5417 cur_arg++;
5418 }
5419 /* now ptr_arg points to the beginning of a word past any possible
5420 * exclamation mark, and cur_arg is the argument which holds this word.
5421 */
5422 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005423 struct tcpcheck_rule *tcpcheck;
5424 char *err = NULL;
5425
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005426 if (!*(args[cur_arg + 1])) {
5427 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
5428 file, linenum, args[0], args[1], ptr_arg);
5429 err_code |= ERR_ALERT | ERR_FATAL;
5430 goto out;
5431 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005432
5433 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5434
5435 tcpcheck->action = TCPCHK_ACT_EXPECT;
5436 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5437 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5438 file, linenum, args[0], args[1], args[2], err);
5439 err_code |= ERR_ALERT | ERR_FATAL;
5440 goto out;
5441 }
5442 tcpcheck->expect_regex = NULL;
5443 tcpcheck->inverse = inverse;
5444
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005445 /* tcpcheck comment */
5446 cur_arg += 2;
5447 if (strcmp(args[cur_arg], "comment") == 0) {
5448 if (!*args[cur_arg + 1]) {
5449 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5450 file, linenum, args[cur_arg + 1]);
5451 err_code |= ERR_ALERT | ERR_FATAL;
5452 goto out;
5453 }
5454 tcpcheck->comment = strdup(args[cur_arg + 1]);
5455 }
5456
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005457 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5458 }
5459 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005460 struct tcpcheck_rule *tcpcheck;
5461
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005462 if (!*(args[cur_arg + 1])) {
5463 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5464 file, linenum, args[0], args[1], ptr_arg);
5465 err_code |= ERR_ALERT | ERR_FATAL;
5466 goto out;
5467 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005468
5469 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5470
5471 tcpcheck->action = TCPCHK_ACT_EXPECT;
5472 tcpcheck->string_len = strlen(args[cur_arg + 1]);
5473 tcpcheck->string = strdup(args[cur_arg + 1]);
5474 tcpcheck->expect_regex = NULL;
5475 tcpcheck->inverse = inverse;
5476
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005477 /* tcpcheck comment */
5478 cur_arg += 2;
5479 if (strcmp(args[cur_arg], "comment") == 0) {
5480 if (!*args[cur_arg + 1]) {
5481 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5482 file, linenum, args[cur_arg + 1]);
5483 err_code |= ERR_ALERT | ERR_FATAL;
5484 goto out;
5485 }
5486 tcpcheck->comment = strdup(args[cur_arg + 1]);
5487 }
5488
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005489 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5490 }
5491 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005492 struct tcpcheck_rule *tcpcheck;
5493
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005494 if (!*(args[cur_arg + 1])) {
5495 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5496 file, linenum, args[0], args[1], ptr_arg);
5497 err_code |= ERR_ALERT | ERR_FATAL;
5498 goto out;
5499 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005500
5501 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5502
5503 tcpcheck->action = TCPCHK_ACT_EXPECT;
5504 tcpcheck->string_len = 0;
5505 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005506 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
5507 error = NULL;
5508 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
5509 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5510 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5511 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005512 err_code |= ERR_ALERT | ERR_FATAL;
5513 goto out;
5514 }
5515 tcpcheck->inverse = inverse;
5516
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005517 /* tcpcheck comment */
5518 cur_arg += 2;
5519 if (strcmp(args[cur_arg], "comment") == 0) {
5520 if (!*args[cur_arg + 1]) {
5521 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5522 file, linenum, args[cur_arg + 1]);
5523 err_code |= ERR_ALERT | ERR_FATAL;
5524 goto out;
5525 }
5526 tcpcheck->comment = strdup(args[cur_arg + 1]);
5527 }
5528
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005529 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5530 }
5531 else {
5532 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
5533 file, linenum, args[0], args[1], ptr_arg);
5534 err_code |= ERR_ALERT | ERR_FATAL;
5535 goto out;
5536 }
5537 }
5538 else {
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005539 Alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005540 err_code |= ERR_ALERT | ERR_FATAL;
5541 goto out;
5542 }
5543 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01005544 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02005545 if (curproxy == &defproxy) {
5546 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005547 err_code |= ERR_ALERT | ERR_FATAL;
5548 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02005549 }
5550
Willy Tarreaub80c2302007-11-30 20:51:32 +01005551 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005552 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005553
5554 if (strcmp(args[1], "fail") == 0) {
5555 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01005556 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01005557 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
5558 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005559 err_code |= ERR_ALERT | ERR_FATAL;
5560 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005561 }
5562
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005563 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
5564 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
5565 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005566 err_code |= ERR_ALERT | ERR_FATAL;
5567 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005568 }
5569 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
5570 }
5571 else {
5572 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005573 err_code |= ERR_ALERT | ERR_FATAL;
5574 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005575 }
5576 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005577#ifdef TPROXY
5578 else if (!strcmp(args[0], "transparent")) {
5579 /* enable transparent proxy connections */
5580 curproxy->options |= PR_O_TRANSP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005581 if (alertif_too_many_args(0, file, linenum, args, &err_code))
5582 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005583 }
5584#endif
5585 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005586 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005587 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005588
Willy Tarreaubaaee002006-06-26 02:48:02 +02005589 if (*(args[1]) == 0) {
5590 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005591 err_code |= ERR_ALERT | ERR_FATAL;
5592 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005593 }
5594 curproxy->maxconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005595 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5596 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005597 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005598 else if (!strcmp(args[0], "backlog")) { /* backlog */
5599 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005600 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005601
5602 if (*(args[1]) == 0) {
5603 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005604 err_code |= ERR_ALERT | ERR_FATAL;
5605 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005606 }
5607 curproxy->backlog = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005608 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5609 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005610 }
Willy Tarreau86034312006-12-29 00:10:33 +01005611 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005612 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005613 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005614
Willy Tarreau86034312006-12-29 00:10:33 +01005615 if (*(args[1]) == 0) {
5616 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005617 err_code |= ERR_ALERT | ERR_FATAL;
5618 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005619 }
5620 curproxy->fullconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005621 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5622 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005623 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005624 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
5625 if (*(args[1]) == 0) {
5626 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005627 err_code |= ERR_ALERT | ERR_FATAL;
5628 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005629 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005630 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
5631 if (err) {
5632 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
5633 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02005634 err_code |= ERR_ALERT | ERR_FATAL;
5635 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005636 }
5637 curproxy->grace = val;
William Lallemanddf1425a2015-04-28 20:17:49 +02005638 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5639 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005640 }
5641 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01005642 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005643 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005644 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005645
Willy Tarreaubaaee002006-06-26 02:48:02 +02005646 if (curproxy == &defproxy) {
5647 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005648 err_code |= ERR_ALERT | ERR_FATAL;
5649 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005650 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005651 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005652 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005653
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02005654 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005655 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005656 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005657 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005658 goto out;
5659 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005660
5661 proto = protocol_by_family(sk->ss_family);
5662 if (!proto || !proto->connect) {
5663 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5664 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005665 err_code |= ERR_ALERT | ERR_FATAL;
5666 goto out;
5667 }
5668
5669 if (port1 != port2) {
5670 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5671 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005672 err_code |= ERR_ALERT | ERR_FATAL;
5673 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005674 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005675
5676 if (!port1) {
5677 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5678 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005679 err_code |= ERR_ALERT | ERR_FATAL;
5680 goto out;
5681 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005682
William Lallemanddf1425a2015-04-28 20:17:49 +02005683 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5684 goto out;
5685
Willy Tarreaud5191e72010-02-09 20:50:45 +01005686 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005687 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005688 }
5689 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005690 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005691 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005692
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005693 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5694 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005695 err_code |= ERR_ALERT | ERR_FATAL;
5696 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005697 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005698 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005699 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005700 /**
5701 * The syntax for hash-type config element is
5702 * hash-type {map-based|consistent} [[<algo>] avalanche]
5703 *
5704 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5705 */
5706 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005707
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005708 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5709 err_code |= ERR_WARN;
5710
5711 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005712 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5713 }
5714 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005715 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5716 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005717 else if (strcmp(args[1], "avalanche") == 0) {
5718 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]);
5719 err_code |= ERR_ALERT | ERR_FATAL;
5720 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005721 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005722 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005723 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005724 err_code |= ERR_ALERT | ERR_FATAL;
5725 goto out;
5726 }
Bhaskar98634f02013-10-29 23:30:51 -04005727
5728 /* set the hash function to use */
5729 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005730 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005731 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005732
5733 /* if consistent with no argument, then avalanche modifier is also applied */
5734 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5735 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005736 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005737 /* set the hash function */
5738 if (!strcmp(args[2], "sdbm")) {
5739 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5740 }
5741 else if (!strcmp(args[2], "djb2")) {
5742 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005743 }
5744 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005745 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005746 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005747 else if (!strcmp(args[2], "crc32")) {
5748 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5749 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005750 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005751 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 -05005752 err_code |= ERR_ALERT | ERR_FATAL;
5753 goto out;
5754 }
5755
5756 /* set the hash modifier */
5757 if (!strcmp(args[3], "avalanche")) {
5758 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5759 }
5760 else if (*args[3]) {
5761 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5762 err_code |= ERR_ALERT | ERR_FATAL;
5763 goto out;
5764 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005765 }
William Lallemanda73203e2012-03-12 12:48:57 +01005766 }
William Lallemanda73203e2012-03-12 12:48:57 +01005767 else if (strcmp(args[0], "unique-id-format") == 0) {
5768 if (!*(args[1])) {
5769 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5770 err_code |= ERR_ALERT | ERR_FATAL;
5771 goto out;
5772 }
William Lallemand3203ff42012-11-11 17:30:56 +01005773 if (*(args[2])) {
5774 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5775 err_code |= ERR_ALERT | ERR_FATAL;
5776 goto out;
5777 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005778 free(curproxy->conf.uniqueid_format_string);
5779 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005780
Willy Tarreau62a61232013-04-12 18:13:46 +02005781 free(curproxy->conf.uif_file);
5782 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5783 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005784 }
William Lallemanda73203e2012-03-12 12:48:57 +01005785
5786 else if (strcmp(args[0], "unique-id-header") == 0) {
5787 if (!*(args[1])) {
5788 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5789 err_code |= ERR_ALERT | ERR_FATAL;
5790 goto out;
5791 }
5792 free(curproxy->header_unique_id);
5793 curproxy->header_unique_id = strdup(args[1]);
5794 }
5795
William Lallemand723b73a2012-02-08 16:37:49 +01005796 else if (strcmp(args[0], "log-format") == 0) {
5797 if (!*(args[1])) {
5798 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5799 err_code |= ERR_ALERT | ERR_FATAL;
5800 goto out;
5801 }
William Lallemand3203ff42012-11-11 17:30:56 +01005802 if (*(args[2])) {
5803 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5804 err_code |= ERR_ALERT | ERR_FATAL;
5805 goto out;
5806 }
Willy Tarreau196729e2012-05-31 19:30:26 +02005807
Willy Tarreau62a61232013-04-12 18:13:46 +02005808 if (curproxy->conf.logformat_string != default_http_log_format &&
5809 curproxy->conf.logformat_string != default_tcp_log_format &&
5810 curproxy->conf.logformat_string != clf_http_log_format)
5811 free(curproxy->conf.logformat_string);
5812 curproxy->conf.logformat_string = strdup(args[1]);
5813
5814 free(curproxy->conf.lfs_file);
5815 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5816 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005817
5818 /* get a chance to improve log-format error reporting by
5819 * reporting the correct line-number when possible.
5820 */
5821 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5822 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5823 file, linenum, curproxy->id);
5824 err_code |= ERR_WARN;
5825 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005826 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02005827 else if (!strcmp(args[0], "log-format-sd")) {
5828 if (!*(args[1])) {
5829 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5830 err_code |= ERR_ALERT | ERR_FATAL;
5831 goto out;
5832 }
5833 if (*(args[2])) {
5834 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5835 err_code |= ERR_ALERT | ERR_FATAL;
5836 goto out;
5837 }
5838
5839 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
5840 free(curproxy->conf.logformat_sd_string);
5841 curproxy->conf.logformat_sd_string = strdup(args[1]);
5842
5843 free(curproxy->conf.lfsd_file);
5844 curproxy->conf.lfsd_file = strdup(curproxy->conf.args.file);
5845 curproxy->conf.lfsd_line = curproxy->conf.args.line;
5846
5847 /* get a chance to improve log-format-sd error reporting by
5848 * reporting the correct line-number when possible.
5849 */
5850 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5851 Warning("parsing [%s:%d] : backend '%s' : 'log-format-sd' directive is ignored in backends.\n",
5852 file, linenum, curproxy->id);
5853 err_code |= ERR_WARN;
5854 }
5855 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01005856 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
5857 if (*(args[1]) == 0) {
5858 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
5859 err_code |= ERR_ALERT | ERR_FATAL;
5860 goto out;
5861 }
Dragan Dosen43885c72015-10-01 13:18:13 +02005862 chunk_destroy(&curproxy->log_tag);
5863 chunk_initstr(&curproxy->log_tag, strdup(args[1]));
Willy Tarreau094af4e2015-01-07 15:03:42 +01005864 }
William Lallemand0f99e342011-10-12 17:50:54 +02005865 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
5866 /* delete previous herited or defined syslog servers */
5867 struct logsrv *back;
5868
5869 if (*(args[1]) != 0) {
5870 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
5871 err_code |= ERR_ALERT | ERR_FATAL;
5872 goto out;
5873 }
5874
William Lallemand723b73a2012-02-08 16:37:49 +01005875 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
5876 LIST_DEL(&tmplogsrv->list);
5877 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02005878 }
5879 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005880 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02005881 struct logsrv *logsrv;
5882
Willy Tarreaubaaee002006-06-26 02:48:02 +02005883 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005884 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01005885 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02005886 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01005887 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02005888 LIST_INIT(&node->list);
5889 LIST_ADDQ(&curproxy->logsrvs, &node->list);
5890 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005891 }
5892 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005893 struct sockaddr_storage *sk;
5894 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02005895 int arg = 0;
5896 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02005897
5898 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005899
Willy Tarreau18324f52014-06-27 18:10:07 +02005900 /* just after the address, a length may be specified */
5901 if (strcmp(args[arg+2], "len") == 0) {
5902 len = atoi(args[arg+3]);
5903 if (len < 80 || len > 65535) {
5904 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
5905 file, linenum, args[arg+3]);
5906 err_code |= ERR_ALERT | ERR_FATAL;
5907 goto out;
5908 }
5909 logsrv->maxlen = len;
5910
5911 /* skip these two args */
5912 arg += 2;
5913 }
5914 else
5915 logsrv->maxlen = MAX_SYSLOG_LEN;
5916
5917 if (logsrv->maxlen > global.max_syslog_len) {
5918 global.max_syslog_len = logsrv->maxlen;
Dragan Dosen59cee972015-09-19 22:09:02 +02005919 logheader = realloc(logheader, global.max_syslog_len + 1);
Dragan Dosen1322d092015-09-22 16:05:32 +02005920 logheader_rfc5424 = realloc(logheader_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02005921 logline = realloc(logline, global.max_syslog_len + 1);
Dragan Dosen0b85ece2015-09-25 19:17:44 +02005922 logline_rfc5424 = realloc(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02005923 }
5924
Dragan Dosen1322d092015-09-22 16:05:32 +02005925 /* after the length, a format may be specified */
5926 if (strcmp(args[arg+2], "format") == 0) {
5927 logsrv->format = get_log_format(args[arg+3]);
5928 if (logsrv->format < 0) {
5929 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
5930 err_code |= ERR_ALERT | ERR_FATAL;
5931 goto out;
5932 }
5933
5934 /* skip these two args */
5935 arg += 2;
5936 }
5937
William Lallemanddf1425a2015-04-28 20:17:49 +02005938 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
5939 goto out;
5940
Willy Tarreau18324f52014-06-27 18:10:07 +02005941 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005942 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005943 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005944 err_code |= ERR_ALERT | ERR_FATAL;
5945 goto out;
5946
Willy Tarreaubaaee002006-06-26 02:48:02 +02005947 }
5948
William Lallemand0f99e342011-10-12 17:50:54 +02005949 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02005950 if (*(args[arg+3])) {
5951 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005952 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005953 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005954 err_code |= ERR_ALERT | ERR_FATAL;
5955 goto out;
5956
Willy Tarreaubaaee002006-06-26 02:48:02 +02005957 }
5958 }
5959
William Lallemand0f99e342011-10-12 17:50:54 +02005960 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02005961 if (*(args[arg+4])) {
5962 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01005963 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005964 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02005965 err_code |= ERR_ALERT | ERR_FATAL;
5966 goto out;
5967
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005968 }
5969 }
5970
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02005971 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005972 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005973 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005974 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005975 goto out;
5976 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005977
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005978 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005979
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005980 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005981 if (port1 != port2) {
5982 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5983 file, linenum, args[0], args[1]);
5984 err_code |= ERR_ALERT | ERR_FATAL;
5985 goto out;
5986 }
5987
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005988 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02005989 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005990 }
William Lallemand0f99e342011-10-12 17:50:54 +02005991
5992 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005993 }
5994 else {
5995 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
5996 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005997 err_code |= ERR_ALERT | ERR_FATAL;
5998 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005999 }
6000 }
6001 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006002 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006003 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01006004 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006005 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006006
Willy Tarreau977b8e42006-12-29 14:19:17 +01006007 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006008 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006009
Willy Tarreaubaaee002006-06-26 02:48:02 +02006010 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006011 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
6012 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02006013 err_code |= ERR_ALERT | ERR_FATAL;
6014 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006015 }
Willy Tarreau368480c2009-03-01 08:27:21 +01006016
6017 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01006018 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6019 free(curproxy->conn_src.iface_name);
6020 curproxy->conn_src.iface_name = NULL;
6021 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01006022
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006023 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006024 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006025 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006026 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006027 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006028 goto out;
6029 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006030
6031 proto = protocol_by_family(sk->ss_family);
6032 if (!proto || !proto->connect) {
6033 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006034 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006035 err_code |= ERR_ALERT | ERR_FATAL;
6036 goto out;
6037 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006038
6039 if (port1 != port2) {
6040 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6041 file, linenum, args[0], args[1]);
6042 err_code |= ERR_ALERT | ERR_FATAL;
6043 goto out;
6044 }
6045
Willy Tarreauef9a3602012-12-08 22:29:20 +01006046 curproxy->conn_src.source_addr = *sk;
6047 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006048
6049 cur_arg = 2;
6050 while (*(args[cur_arg])) {
6051 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau29fbe512015-08-20 19:35:14 +02006052#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006053 if (!*args[cur_arg + 1]) {
6054 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
6055 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006056 err_code |= ERR_ALERT | ERR_FATAL;
6057 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006058 }
6059
6060 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006061 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6062 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006063 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006064 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6065 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02006066 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
6067 char *name, *end;
6068
6069 name = args[cur_arg+1] + 7;
6070 while (isspace(*name))
6071 name++;
6072
6073 end = name;
6074 while (*end && !isspace(*end) && *end != ',' && *end != ')')
6075 end++;
6076
Willy Tarreauef9a3602012-12-08 22:29:20 +01006077 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6078 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
6079 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
6080 curproxy->conn_src.bind_hdr_len = end - name;
6081 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
6082 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
6083 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02006084
6085 /* now look for an occurrence number */
6086 while (isspace(*end))
6087 end++;
6088 if (*end == ',') {
6089 end++;
6090 name = end;
6091 if (*end == '-')
6092 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01006093 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02006094 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01006095 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006096 }
6097
Willy Tarreauef9a3602012-12-08 22:29:20 +01006098 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02006099 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
6100 " occurrences values smaller than %d.\n",
6101 file, linenum, MAX_HDR_HISTORY);
6102 err_code |= ERR_ALERT | ERR_FATAL;
6103 goto out;
6104 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006105 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01006106 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006107
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006108 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006109 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006110 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006111 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006112 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006113 goto out;
6114 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006115
6116 proto = protocol_by_family(sk->ss_family);
6117 if (!proto || !proto->connect) {
6118 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
6119 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006120 err_code |= ERR_ALERT | ERR_FATAL;
6121 goto out;
6122 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006123
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006124 if (port1 != port2) {
6125 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6126 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006127 err_code |= ERR_ALERT | ERR_FATAL;
6128 goto out;
6129 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006130 curproxy->conn_src.tproxy_addr = *sk;
6131 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006132 }
6133 global.last_checks |= LSTCHK_NETADM;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006134#else /* no TPROXY support */
6135 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01006136 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006137 err_code |= ERR_ALERT | ERR_FATAL;
6138 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006139#endif
6140 cur_arg += 2;
6141 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01006142 }
6143
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006144 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
6145#ifdef SO_BINDTODEVICE
6146 if (!*args[cur_arg + 1]) {
6147 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
6148 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006149 err_code |= ERR_ALERT | ERR_FATAL;
6150 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006151 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006152 free(curproxy->conn_src.iface_name);
6153 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
6154 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006155 global.last_checks |= LSTCHK_NETADM;
6156#else
6157 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
6158 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02006159 err_code |= ERR_ALERT | ERR_FATAL;
6160 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01006161#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006162 cur_arg += 2;
6163 continue;
6164 }
6165 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02006166 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006167 err_code |= ERR_ALERT | ERR_FATAL;
6168 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006169 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006170 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006171 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
6172 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
6173 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02006174 err_code |= ERR_ALERT | ERR_FATAL;
6175 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006176 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006177 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006178 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006179 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6180 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006181 err_code |= ERR_ALERT | ERR_FATAL;
6182 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006183 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006184
6185 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006186 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006187 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006188 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006189 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006190 }
6191 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006192 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006193 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006194 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006195 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006196 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006197 }
6198 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006199 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006200 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006201 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006202 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006203 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006204 }
6205 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006206 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006207 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006208 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006209 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006210 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006211 }
6212 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006213 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006214 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006215 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006216 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006217 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006218 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006219 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006220 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006221 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006222 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006223 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006224 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006225 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006226 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006227 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006228 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6229 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006230 err_code |= ERR_ALERT | ERR_FATAL;
6231 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006232 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006233
6234 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006235 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006236 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006237 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006238 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006239 }
6240 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006241 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006242 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006243 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006244 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006245 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006246 }
6247 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006248 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006249 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006250 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006251 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006252 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006253 }
6254 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006255 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006256 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006257 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006258 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006259 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006260 }
6261 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006262 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006263 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006264 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006265 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006266 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006267 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006268 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006269 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006270 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006271 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006272 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006273 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006274 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006275 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006276 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006277
Willy Tarreaubaaee002006-06-26 02:48:02 +02006278 if (curproxy == &defproxy) {
6279 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006280 err_code |= ERR_ALERT | ERR_FATAL;
6281 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006282 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006283 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006284 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006285
Willy Tarreaubaaee002006-06-26 02:48:02 +02006286 if (*(args[1]) == 0) {
6287 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006288 err_code |= ERR_ALERT | ERR_FATAL;
6289 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006290 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006291
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006292 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006293 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6294 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6295 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006296 err_code |= ERR_ALERT | ERR_FATAL;
6297 goto out;
6298 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006299 err_code |= warnif_cond_conflicts(cond,
6300 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6301 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006302 }
6303 else if (*args[2]) {
6304 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6305 file, linenum, args[0], args[2]);
6306 err_code |= ERR_ALERT | ERR_FATAL;
6307 goto out;
6308 }
6309
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006310 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006311 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006312 wl->s = strdup(args[1]);
6313 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02006314 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006315 }
6316 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006317 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006318 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6319 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006320 err_code |= ERR_ALERT | ERR_FATAL;
6321 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006322 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006323
Willy Tarreauade5ec42010-01-28 19:33:49 +01006324 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006325 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006326 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006327 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006328 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006329 }
6330 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006331 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006332 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006333 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006334 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006335 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006336 }
6337 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006338 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006339 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006340 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006341 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006342 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006343 }
6344 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006345 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006346 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6347 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006348 err_code |= ERR_ALERT | ERR_FATAL;
6349 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006350 }
6351
Willy Tarreauade5ec42010-01-28 19:33:49 +01006352 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006353 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006354 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006355 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006356 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006357 }
6358 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006359 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006360 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006361 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006362 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006363 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006364 }
6365 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006366 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006367 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006368 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006369 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006370 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006371 }
6372 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006373 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006374
Willy Tarreaubaaee002006-06-26 02:48:02 +02006375 if (curproxy == &defproxy) {
6376 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006377 err_code |= ERR_ALERT | ERR_FATAL;
6378 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006379 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006380 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006381 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006382
Willy Tarreaubaaee002006-06-26 02:48:02 +02006383 if (*(args[1]) == 0) {
6384 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006385 err_code |= ERR_ALERT | ERR_FATAL;
6386 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006387 }
6388
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006389 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006390 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6391 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6392 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006393 err_code |= ERR_ALERT | ERR_FATAL;
6394 goto out;
6395 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006396 err_code |= warnif_cond_conflicts(cond,
6397 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
6398 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006399 }
6400 else if (*args[2]) {
6401 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6402 file, linenum, args[0], args[2]);
6403 err_code |= ERR_ALERT | ERR_FATAL;
6404 goto out;
6405 }
6406
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006407 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006408 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006409 wl->s = strdup(args[1]);
6410 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006411 }
6412 else if (!strcmp(args[0], "errorloc") ||
6413 !strcmp(args[0], "errorloc302") ||
6414 !strcmp(args[0], "errorloc303")) { /* error location */
6415 int errnum, errlen;
6416 char *err;
6417
Willy Tarreau977b8e42006-12-29 14:19:17 +01006418 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006419 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006420
Willy Tarreaubaaee002006-06-26 02:48:02 +02006421 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006422 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006423 err_code |= ERR_ALERT | ERR_FATAL;
6424 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006425 }
6426
6427 errnum = atol(args[1]);
6428 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006429 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
6430 err = malloc(errlen);
6431 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006432 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006433 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
6434 err = malloc(errlen);
6435 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006436 }
6437
Willy Tarreau0f772532006-12-23 20:51:41 +01006438 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6439 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006440 chunk_destroy(&curproxy->errmsg[rc]);
6441 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01006442 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006443 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006444 }
Willy Tarreau0f772532006-12-23 20:51:41 +01006445
6446 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006447 Warning("parsing [%s:%d] : status code %d not handled by '%s', error relocation will be ignored.\n",
6448 file, linenum, errnum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006449 free(err);
6450 }
6451 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02006452 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
6453 int errnum, errlen, fd;
6454 char *err;
6455 struct stat stat;
6456
6457 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006458 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006459
6460 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006461 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006462 err_code |= ERR_ALERT | ERR_FATAL;
6463 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006464 }
6465
6466 fd = open(args[2], O_RDONLY);
6467 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
6468 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
6469 file, linenum, args[2], args[1]);
6470 if (fd >= 0)
6471 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02006472 err_code |= ERR_ALERT | ERR_FATAL;
6473 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006474 }
6475
Willy Tarreau27a674e2009-08-17 07:23:33 +02006476 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02006477 errlen = stat.st_size;
6478 } else {
6479 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02006480 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02006481 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02006482 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006483 }
6484
6485 err = malloc(errlen); /* malloc() must succeed during parsing */
6486 errnum = read(fd, err, errlen);
6487 if (errnum != errlen) {
6488 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
6489 file, linenum, args[2], args[1]);
6490 close(fd);
6491 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02006492 err_code |= ERR_ALERT | ERR_FATAL;
6493 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006494 }
6495 close(fd);
6496
6497 errnum = atol(args[1]);
6498 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6499 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006500 chunk_destroy(&curproxy->errmsg[rc]);
6501 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02006502 break;
6503 }
6504 }
6505
6506 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006507 Warning("parsing [%s:%d] : status code %d not handled by '%s', error customization will be ignored.\n",
6508 file, linenum, errnum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006509 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006510 free(err);
6511 }
6512 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006513 else if (!strcmp(args[0], "compression")) {
6514 struct comp *comp;
6515 if (curproxy->comp == NULL) {
6516 comp = calloc(1, sizeof(struct comp));
6517 curproxy->comp = comp;
6518 } else {
6519 comp = curproxy->comp;
6520 }
6521
6522 if (!strcmp(args[1], "algo")) {
6523 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01006524 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01006525
William Lallemand82fe75c2012-10-23 10:25:10 +02006526 cur_arg = 2;
6527 if (!*args[cur_arg]) {
6528 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
6529 file, linenum, args[0]);
6530 err_code |= ERR_ALERT | ERR_FATAL;
6531 goto out;
6532 }
6533 while (*(args[cur_arg])) {
6534 if (comp_append_algo(comp, args[cur_arg]) < 0) {
6535 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
6536 file, linenum, args[0], args[cur_arg]);
6537 err_code |= ERR_ALERT | ERR_FATAL;
6538 goto out;
6539 }
William Lallemand552df672012-11-07 13:21:47 +01006540 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
6541 curproxy->comp->algos->end(&ctx);
6542 } else {
6543 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
6544 file, linenum, args[0], args[cur_arg]);
6545 err_code |= ERR_ALERT | ERR_FATAL;
6546 goto out;
6547 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006548 cur_arg ++;
6549 continue;
6550 }
6551 }
Willy Tarreau70737d12012-10-27 00:34:28 +02006552 else if (!strcmp(args[1], "offload")) {
6553 comp->offload = 1;
6554 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006555 else if (!strcmp(args[1], "type")) {
6556 int cur_arg;
6557 cur_arg = 2;
6558 if (!*args[cur_arg]) {
6559 Alert("parsing [%s:%d] : '%s' expects <type>\n",
6560 file, linenum, args[0]);
6561 err_code |= ERR_ALERT | ERR_FATAL;
6562 goto out;
6563 }
6564 while (*(args[cur_arg])) {
6565 comp_append_type(comp, args[cur_arg]);
6566 cur_arg ++;
6567 continue;
6568 }
6569 }
6570 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02006571 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02006572 file, linenum, args[0]);
6573 err_code |= ERR_ALERT | ERR_FATAL;
6574 goto out;
6575 }
6576 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006577 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006578 struct cfg_kw_list *kwl;
6579 int index;
6580
6581 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6582 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6583 if (kwl->kw[index].section != CFG_LISTEN)
6584 continue;
6585 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6586 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006587 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006588 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006589 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006590 err_code |= ERR_ALERT | ERR_FATAL;
6591 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006592 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006593 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006594 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006595 err_code |= ERR_WARN;
6596 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006597 }
Willy Tarreau93893792009-07-23 13:19:11 +02006598 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006599 }
6600 }
6601 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006602
Willy Tarreau6daf3432008-01-22 16:44:08 +01006603 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006604 err_code |= ERR_ALERT | ERR_FATAL;
6605 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006606 }
Willy Tarreau93893792009-07-23 13:19:11 +02006607 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006608 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006609 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006610}
6611
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006612int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006613cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
6614{
6615#ifdef CONFIG_HAP_NS
6616 const char *err;
6617 const char *item = args[0];
6618
6619 if (!strcmp(item, "namespace_list")) {
6620 return 0;
6621 }
6622 else if (!strcmp(item, "namespace")) {
6623 size_t idx = 1;
6624 const char *current;
6625 while (*(current = args[idx++])) {
6626 err = invalid_char(current);
6627 if (err) {
6628 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6629 file, linenum, *err, item, current);
6630 return ERR_ALERT | ERR_FATAL;
6631 }
6632
6633 if (netns_store_lookup(current, strlen(current))) {
6634 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
6635 file, linenum, current);
6636 return ERR_ALERT | ERR_FATAL;
6637 }
6638 if (!netns_store_insert(current)) {
6639 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
6640 file, linenum, current);
6641 return ERR_ALERT | ERR_FATAL;
6642 }
6643 }
6644 }
6645
6646 return 0;
6647#else
6648 Alert("parsing [%s:%d]: namespace support is not compiled in.",
6649 file, linenum);
6650 return ERR_ALERT | ERR_FATAL;
6651#endif
6652}
6653
6654int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006655cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6656{
6657
6658 int err_code = 0;
6659 const char *err;
6660
6661 if (!strcmp(args[0], "userlist")) { /* new userlist */
6662 struct userlist *newul;
6663
6664 if (!*args[1]) {
6665 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6666 file, linenum, args[0]);
6667 err_code |= ERR_ALERT | ERR_FATAL;
6668 goto out;
6669 }
William Lallemand6e62fb62015-04-28 16:55:23 +02006670 if (alertif_too_many_args(1, file, linenum, args, &err_code))
6671 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006672
6673 err = invalid_char(args[1]);
6674 if (err) {
6675 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6676 file, linenum, *err, args[0], args[1]);
6677 err_code |= ERR_ALERT | ERR_FATAL;
6678 goto out;
6679 }
6680
6681 for (newul = userlist; newul; newul = newul->next)
6682 if (!strcmp(newul->name, args[1])) {
6683 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6684 file, linenum, args[1]);
6685 err_code |= ERR_WARN;
6686 goto out;
6687 }
6688
6689 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
6690 if (!newul) {
6691 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6692 err_code |= ERR_ALERT | ERR_ABORT;
6693 goto out;
6694 }
6695
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006696 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006697 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006698 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6699 err_code |= ERR_ALERT | ERR_ABORT;
6700 goto out;
6701 }
6702
6703 newul->next = userlist;
6704 userlist = newul;
6705
6706 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006707 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006708 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006709 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006710
6711 if (!*args[1]) {
6712 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6713 file, linenum, args[0]);
6714 err_code |= ERR_ALERT | ERR_FATAL;
6715 goto out;
6716 }
6717
6718 err = invalid_char(args[1]);
6719 if (err) {
6720 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6721 file, linenum, *err, args[0], args[1]);
6722 err_code |= ERR_ALERT | ERR_FATAL;
6723 goto out;
6724 }
6725
William Lallemand4ac9f542015-05-28 18:03:51 +02006726 if (!userlist)
6727 goto out;
6728
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006729 for (ag = userlist->groups; ag; ag = ag->next)
6730 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006731 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6732 file, linenum, args[1], userlist->name);
6733 err_code |= ERR_ALERT;
6734 goto out;
6735 }
6736
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006737 ag = calloc(1, sizeof(*ag));
6738 if (!ag) {
6739 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6740 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006741 goto out;
6742 }
6743
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006744 ag->name = strdup(args[1]);
6745 if (!ag) {
6746 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6747 err_code |= ERR_ALERT | ERR_ABORT;
6748 goto out;
6749 }
6750
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006751 cur_arg = 2;
6752
6753 while (*args[cur_arg]) {
6754 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006755 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006756 cur_arg += 2;
6757 continue;
6758 } else {
6759 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6760 file, linenum, args[0]);
6761 err_code |= ERR_ALERT | ERR_FATAL;
6762 goto out;
6763 }
6764 }
6765
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006766 ag->next = userlist->groups;
6767 userlist->groups = ag;
6768
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006769 } else if (!strcmp(args[0], "user")) { /* new user */
6770 struct auth_users *newuser;
6771 int cur_arg;
6772
6773 if (!*args[1]) {
6774 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6775 file, linenum, args[0]);
6776 err_code |= ERR_ALERT | ERR_FATAL;
6777 goto out;
6778 }
William Lallemand4ac9f542015-05-28 18:03:51 +02006779 if (!userlist)
6780 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006781
6782 for (newuser = userlist->users; newuser; newuser = newuser->next)
6783 if (!strcmp(newuser->user, args[1])) {
6784 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6785 file, linenum, args[1], userlist->name);
6786 err_code |= ERR_ALERT;
6787 goto out;
6788 }
6789
6790 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
6791 if (!newuser) {
6792 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6793 err_code |= ERR_ALERT | ERR_ABORT;
6794 goto out;
6795 }
6796
6797 newuser->user = strdup(args[1]);
6798
6799 newuser->next = userlist->users;
6800 userlist->users = newuser;
6801
6802 cur_arg = 2;
6803
6804 while (*args[cur_arg]) {
6805 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006806#ifdef CONFIG_HAP_CRYPT
6807 if (!crypt("", args[cur_arg + 1])) {
6808 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6809 file, linenum, newuser->user);
6810 err_code |= ERR_ALERT | ERR_FATAL;
6811 goto out;
6812 }
6813#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006814 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6815 file, linenum);
6816 err_code |= ERR_ALERT;
6817#endif
6818 newuser->pass = strdup(args[cur_arg + 1]);
6819 cur_arg += 2;
6820 continue;
6821 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6822 newuser->pass = strdup(args[cur_arg + 1]);
6823 newuser->flags |= AU_O_INSECURE;
6824 cur_arg += 2;
6825 continue;
6826 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006827 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006828 cur_arg += 2;
6829 continue;
6830 } else {
6831 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6832 file, linenum, args[0]);
6833 err_code |= ERR_ALERT | ERR_FATAL;
6834 goto out;
6835 }
6836 }
6837 } else {
6838 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6839 err_code |= ERR_ALERT | ERR_FATAL;
6840 }
6841
6842out:
6843 return err_code;
6844}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006845
6846/*
6847 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006848 * Returns the error code, 0 if OK, or any combination of :
6849 * - ERR_ABORT: must abort ASAP
6850 * - ERR_FATAL: we can continue parsing but not start the service
6851 * - ERR_WARN: a warning has been emitted
6852 * - ERR_ALERT: an alert has been emitted
6853 * Only the two first ones can stop processing, the two others are just
6854 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006855 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006856int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006857{
William Lallemand64e84512015-05-12 14:25:37 +02006858 char *thisline;
6859 int linesize = LINESIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006860 FILE *f;
6861 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02006862 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006863 struct cfg_section *cs = NULL;
6864 struct cfg_section *ics;
William Lallemand64e84512015-05-12 14:25:37 +02006865 int readbytes = 0;
6866
6867 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
William Lallemandb2f07452015-05-12 14:27:13 +02006868 Alert("parsing [%s] : out of memory.\n", file);
William Lallemand64e84512015-05-12 14:25:37 +02006869 return -1;
6870 }
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006871
6872 /* Register internal sections */
6873 if (!cfg_register_section("listen", cfg_parse_listen) ||
6874 !cfg_register_section("frontend", cfg_parse_listen) ||
6875 !cfg_register_section("backend", cfg_parse_listen) ||
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006876 !cfg_register_section("defaults", cfg_parse_listen) ||
6877 !cfg_register_section("global", cfg_parse_global) ||
6878 !cfg_register_section("userlist", cfg_parse_users) ||
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006879 !cfg_register_section("peers", cfg_parse_peers) ||
Simon Horman0d16a402015-01-30 11:22:58 +09006880 !cfg_register_section("mailers", cfg_parse_mailers) ||
Baptiste Assmann325137d2015-04-13 23:40:55 +02006881 !cfg_register_section("namespace_list", cfg_parse_netns) ||
6882 !cfg_register_section("resolvers", cfg_parse_resolvers))
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006883 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006884
Willy Tarreaubaaee002006-06-26 02:48:02 +02006885 if ((f=fopen(file,"r")) == NULL)
6886 return -1;
6887
William Lallemandb2f07452015-05-12 14:27:13 +02006888next_line:
William Lallemand64e84512015-05-12 14:25:37 +02006889 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02006890 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006891 char *end;
6892 char *args[MAX_LINE_ARGS + 1];
6893 char *line = thisline;
William Lallemandf9873ba2015-05-05 17:37:14 +02006894 int dquote = 0; /* double quote */
6895 int squote = 0; /* simple quote */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006896
Willy Tarreaubaaee002006-06-26 02:48:02 +02006897 linenum++;
6898
6899 end = line + strlen(line);
6900
William Lallemand64e84512015-05-12 14:25:37 +02006901 if (end-line == linesize-1 && *(end-1) != '\n') {
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006902 /* Check if we reached the limit and the last char is not \n.
6903 * Watch out for the last line without the terminating '\n'!
6904 */
William Lallemand64e84512015-05-12 14:25:37 +02006905 char *newline;
6906 int newlinesize = linesize * 2;
6907
6908 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
6909 if (newline == NULL) {
6910 Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
6911 file, linenum);
6912 err_code |= ERR_ALERT | ERR_FATAL;
6913 continue;
6914 }
6915
6916 readbytes = linesize - 1;
6917 linesize = newlinesize;
6918 thisline = newline;
6919 continue;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006920 }
6921
William Lallemand64e84512015-05-12 14:25:37 +02006922 readbytes = 0;
6923
Willy Tarreaubaaee002006-06-26 02:48:02 +02006924 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006925 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006926 line++;
William Lallemandf9873ba2015-05-05 17:37:14 +02006927
Willy Tarreaubaaee002006-06-26 02:48:02 +02006928 arg = 0;
6929 args[arg] = line;
6930
6931 while (*line && arg < MAX_LINE_ARGS) {
William Lallemandf9873ba2015-05-05 17:37:14 +02006932 if (*line == '"' && !squote) { /* double quote outside single quotes */
6933 if (dquote)
6934 dquote = 0;
6935 else
6936 dquote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02006937 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02006938 end--;
6939 }
6940 else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
6941 if (squote)
6942 squote = 0;
6943 else
6944 squote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02006945 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02006946 end--;
6947 }
6948 else if (*line == '\\' && !squote) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006949 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
6950 * C equivalent value. Other combinations left unchanged (eg: \1).
6951 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006952 int skip = 0;
6953 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
6954 *line = line[1];
6955 skip = 1;
6956 }
6957 else if (line[1] == 'r') {
6958 *line = '\r';
6959 skip = 1;
William Lallemandf9873ba2015-05-05 17:37:14 +02006960 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006961 else if (line[1] == 'n') {
6962 *line = '\n';
6963 skip = 1;
6964 }
6965 else if (line[1] == 't') {
6966 *line = '\t';
6967 skip = 1;
6968 }
6969 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01006970 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006971 unsigned char hex1, hex2;
6972 hex1 = toupper(line[2]) - '0';
6973 hex2 = toupper(line[3]) - '0';
6974 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
6975 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
6976 *line = (hex1<<4) + hex2;
6977 skip = 3;
6978 }
6979 else {
6980 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006981 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006982 }
William Lallemandf9873ba2015-05-05 17:37:14 +02006983 } else if (line[1] == '"') {
6984 *line = '"';
6985 skip = 1;
6986 } else if (line[1] == '\'') {
6987 *line = '\'';
6988 skip = 1;
William Lallemandb2f07452015-05-12 14:27:13 +02006989 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
6990 *line = '$';
6991 skip = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006992 }
6993 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01006994 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006995 end -= skip;
6996 }
6997 line++;
6998 }
William Lallemandf9873ba2015-05-05 17:37:14 +02006999 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007000 /* end of string, end of loop */
7001 *line = 0;
7002 break;
7003 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007004 else if (!squote && !dquote && isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007005 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007006 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007007 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007008 line++;
7009 args[++arg] = line;
7010 }
William Lallemandb2f07452015-05-12 14:27:13 +02007011 else if (dquote && *line == '$') {
7012 /* environment variables are evaluated inside double quotes */
7013 char *var_beg;
7014 char *var_end;
7015 char save_char;
7016 char *value;
7017 int val_len;
7018 int newlinesize;
7019 int braces = 0;
7020
7021 var_beg = line + 1;
7022 var_end = var_beg;
7023
7024 if (*var_beg == '{') {
7025 var_beg++;
7026 var_end++;
7027 braces = 1;
7028 }
7029
7030 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
7031 Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
7032 err_code |= ERR_ALERT | ERR_FATAL;
7033 goto next_line; /* skip current line */
7034 }
7035
7036 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
7037 var_end++;
7038
7039 save_char = *var_end;
7040 *var_end = '\0';
7041 value = getenv(var_beg);
7042 *var_end = save_char;
7043 val_len = value ? strlen(value) : 0;
7044
7045 if (braces) {
7046 if (*var_end == '}') {
7047 var_end++;
7048 braces = 0;
7049 } else {
7050 Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
7051 err_code |= ERR_ALERT | ERR_FATAL;
7052 goto next_line; /* skip current line */
7053 }
7054 }
7055
7056 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
7057
7058 /* if not enough space in thisline */
7059 if (newlinesize > linesize) {
7060 char *newline;
7061
7062 newline = realloc(thisline, newlinesize * sizeof(*thisline));
7063 if (newline == NULL) {
7064 Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
7065 err_code |= ERR_ALERT | ERR_FATAL;
7066 goto next_line; /* slip current line */
7067 }
7068 /* recompute pointers if realloc returns a new pointer */
7069 if (newline != thisline) {
7070 int i;
7071 int diff;
7072
7073 for (i = 0; i <= arg; i++) {
7074 diff = args[i] - thisline;
7075 args[i] = newline + diff;
7076 }
7077
7078 diff = var_end - thisline;
7079 var_end = newline + diff;
7080 diff = end - thisline;
7081 end = newline + diff;
7082 diff = line - thisline;
7083 line = newline + diff;
7084 thisline = newline;
7085 }
7086 linesize = newlinesize;
7087 }
7088
7089 /* insert value inside the line */
7090 memmove(line + val_len, var_end, end - var_end + 1);
7091 memcpy(line, value, val_len);
7092 end += val_len - (var_end - line);
7093 line += val_len;
7094 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007095 else {
7096 line++;
7097 }
7098 }
William Lallemandb2f07452015-05-12 14:27:13 +02007099
William Lallemandf9873ba2015-05-05 17:37:14 +02007100 if (dquote) {
7101 Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
7102 err_code |= ERR_ALERT | ERR_FATAL;
7103 }
7104
7105 if (squote) {
7106 Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
7107 err_code |= ERR_ALERT | ERR_FATAL;
7108 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007109
7110 /* empty line */
7111 if (!**args)
7112 continue;
7113
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007114 if (*line) {
7115 /* we had to stop due to too many args.
7116 * Let's terminate the string, print the offending part then cut the
7117 * last arg.
7118 */
7119 while (*line && *line != '#' && *line != '\n' && *line != '\r')
7120 line++;
7121 *line = '\0';
7122
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01007123 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01007124 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007125 err_code |= ERR_ALERT | ERR_FATAL;
7126 args[arg] = line;
7127 }
7128
Willy Tarreau540abe42007-05-02 20:50:16 +02007129 /* zero out remaining args and ensure that at least one entry
7130 * is zeroed out.
7131 */
7132 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007133 args[arg] = line;
7134 }
7135
Willy Tarreau3842f002009-06-14 11:39:52 +02007136 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007137 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02007138 char *tmp;
7139
Willy Tarreau3842f002009-06-14 11:39:52 +02007140 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02007141 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007142 for (arg=0; *args[arg+1]; arg++)
7143 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02007144 *tmp = '\0'; // fix the next arg to \0
7145 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007146 }
Willy Tarreau3842f002009-06-14 11:39:52 +02007147 else if (!strcmp(args[0], "default")) {
7148 kwm = KWM_DEF;
7149 for (arg=0; *args[arg+1]; arg++)
7150 args[arg] = args[arg+1]; // shift args after inversion
7151 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007152
William Lallemand0f99e342011-10-12 17:50:54 +02007153 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
7154 strcmp(args[0], "log") != 0) {
7155 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02007156 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007157 }
7158
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007159 /* detect section start */
7160 list_for_each_entry(ics, &sections, list) {
7161 if (strcmp(args[0], ics->section_name) == 0) {
7162 cursection = ics->section_name;
7163 cs = ics;
7164 break;
7165 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007166 }
7167
Willy Tarreaubaaee002006-06-26 02:48:02 +02007168 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007169 if (cs)
7170 err_code |= cs->section_parser(file, linenum, args, kwm);
7171 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007172 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007173 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007174 }
Willy Tarreau058e9072009-07-20 09:30:05 +02007175
7176 if (err_code & ERR_ABORT)
7177 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007178 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01007179 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02007180 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007181 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02007182 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007183}
7184
Willy Tarreau64ab6072014-09-16 12:17:36 +02007185/* This function propagates processes from frontend <from> to backend <to> so
7186 * that it is always guaranteed that a backend pointed to by a frontend is
7187 * bound to all of its processes. After that, if the target is a "listen"
7188 * instance, the function recursively descends the target's own targets along
Willy Tarreau98d04852015-05-26 12:18:29 +02007189 * default_backend and use_backend rules. Since the bits are
Willy Tarreau64ab6072014-09-16 12:17:36 +02007190 * checked first to ensure that <to> is already bound to all processes of
7191 * <from>, there is no risk of looping and we ensure to follow the shortest
7192 * path to the destination.
7193 *
7194 * It is possible to set <to> to NULL for the first call so that the function
7195 * takes care of visiting the initial frontend in <from>.
7196 *
7197 * It is important to note that the function relies on the fact that all names
7198 * have already been resolved.
7199 */
7200void propagate_processes(struct proxy *from, struct proxy *to)
7201{
7202 struct switching_rule *rule;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007203
7204 if (to) {
7205 /* check whether we need to go down */
7206 if (from->bind_proc &&
7207 (from->bind_proc & to->bind_proc) == from->bind_proc)
7208 return;
7209
7210 if (!from->bind_proc && !to->bind_proc)
7211 return;
7212
7213 to->bind_proc = from->bind_proc ?
7214 (to->bind_proc | from->bind_proc) : 0;
7215
7216 /* now propagate down */
7217 from = to;
7218 }
7219
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01007220 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02007221 return;
7222
Willy Tarreauf6b70012014-12-18 14:00:43 +01007223 if (from->state == PR_STSTOPPED)
7224 return;
7225
Willy Tarreau64ab6072014-09-16 12:17:36 +02007226 /* default_backend */
7227 if (from->defbe.be)
7228 propagate_processes(from, from->defbe.be);
7229
7230 /* use_backend */
7231 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02007232 if (rule->dynamic)
7233 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007234 to = rule->be.backend;
7235 propagate_processes(from, to);
7236 }
Willy Tarreau64ab6072014-09-16 12:17:36 +02007237}
7238
Willy Tarreaubb925012009-07-23 13:36:36 +02007239/*
7240 * Returns the error code, 0 if OK, or any combination of :
7241 * - ERR_ABORT: must abort ASAP
7242 * - ERR_FATAL: we can continue parsing but not start the service
7243 * - ERR_WARN: a warning has been emitted
7244 * - ERR_ALERT: an alert has been emitted
7245 * Only the two first ones can stop processing, the two others are just
7246 * indicators.
7247 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007248int check_config_validity()
7249{
7250 int cfgerr = 0;
7251 struct proxy *curproxy = NULL;
7252 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02007253 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007254 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007255 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007256
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007257 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007258 /*
7259 * Now, check for the integrity of all that we have collected.
7260 */
7261
7262 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02007263 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007264
Willy Tarreau193b8c62012-11-22 00:17:38 +01007265 if (!global.tune.max_http_hdr)
7266 global.tune.max_http_hdr = MAX_HTTP_HDR;
7267
7268 if (!global.tune.cookie_len)
7269 global.tune.cookie_len = CAPTURE_LEN;
7270
7271 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
7272
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007273 /* Post initialisation of the users and groups lists. */
7274 err_code = userlist_postinit();
7275 if (err_code != ERR_NONE)
7276 goto out;
7277
Willy Tarreau55bc0f82009-03-15 14:51:53 +01007278 /* first, we will invert the proxy list order */
7279 curproxy = NULL;
7280 while (proxy) {
7281 struct proxy *next;
7282
7283 next = proxy->next;
7284 proxy->next = curproxy;
7285 curproxy = proxy;
7286 if (!next)
7287 break;
7288 proxy = next;
7289 }
7290
Willy Tarreau419ead82014-09-16 13:41:21 +02007291 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007292 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007293 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01007294 struct sticking_rule *mrule;
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007295 struct act_rule *trule;
7296 struct act_rule *hrqrule;
Dragan Dosen1322d092015-09-22 16:05:32 +02007297 struct logsrv *tmplogsrv;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007298 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01007299 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007300
Willy Tarreau050536d2012-10-04 08:47:34 +02007301 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007302 /* proxy ID not set, use automatic numbering with first
7303 * spare entry starting with next_pxid.
7304 */
7305 next_pxid = get_next_id(&used_proxy_id, next_pxid);
7306 curproxy->conf.id.key = curproxy->uuid = next_pxid;
7307 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007308 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007309 next_pxid++;
7310
Willy Tarreau55ea7572007-06-17 19:56:27 +02007311
Willy Tarreaubaaee002006-06-26 02:48:02 +02007312 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02007313 /* ensure we don't keep listeners uselessly bound */
7314 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02007315 free((void *)curproxy->table.peers.name);
7316 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007317 continue;
7318 }
7319
Willy Tarreau102df612014-05-07 23:56:38 +02007320 /* Check multi-process mode compatibility for the current proxy */
7321
7322 if (curproxy->bind_proc) {
7323 /* an explicit bind-process was specified, let's check how many
7324 * processes remain.
7325 */
David Carliere6c39412015-07-02 07:00:17 +00007326 nbproc = my_popcountl(curproxy->bind_proc);
Willy Tarreau102df612014-05-07 23:56:38 +02007327
7328 curproxy->bind_proc &= nbits(global.nbproc);
7329 if (!curproxy->bind_proc && nbproc == 1) {
7330 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);
7331 curproxy->bind_proc = 1;
7332 }
7333 else if (!curproxy->bind_proc && nbproc > 1) {
7334 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);
7335 curproxy->bind_proc = 0;
7336 }
7337 }
7338
Willy Tarreau3d209582014-05-09 17:06:11 +02007339 /* check and reduce the bind-proc of each listener */
7340 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7341 unsigned long mask;
7342
7343 if (!bind_conf->bind_proc)
7344 continue;
7345
7346 mask = nbits(global.nbproc);
7347 if (curproxy->bind_proc)
7348 mask &= curproxy->bind_proc;
7349 /* mask cannot be null here thanks to the previous checks */
7350
David Carliere6c39412015-07-02 07:00:17 +00007351 nbproc = my_popcountl(bind_conf->bind_proc);
Willy Tarreau3d209582014-05-09 17:06:11 +02007352 bind_conf->bind_proc &= mask;
7353
7354 if (!bind_conf->bind_proc && nbproc == 1) {
7355 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",
7356 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7357 bind_conf->bind_proc = mask & ~(mask - 1);
7358 }
7359 else if (!bind_conf->bind_proc && nbproc > 1) {
7360 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",
7361 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7362 bind_conf->bind_proc = 0;
7363 }
7364 }
7365
Willy Tarreauff01a212009-03-15 13:46:16 +01007366 switch (curproxy->mode) {
7367 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007368 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007369 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007370 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
7371 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007372 cfgerr++;
7373 }
7374
7375 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007376 Warning("config : servers will be ignored for %s '%s'.\n",
7377 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007378 break;
7379
7380 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007381 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007382 break;
7383
7384 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01007385 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01007386 break;
7387 }
7388
Willy Tarreauf3934b82015-08-11 11:36:45 +02007389 if ((curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->conf.listeners)) {
7390 Warning("config : %s '%s' has no 'bind' directive. Please declare it as a backend if this was intended.\n",
7391 proxy_type_str(curproxy), curproxy->id);
7392 err_code |= ERR_WARN;
7393 }
7394
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007395 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007396 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007397 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007398 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
7399 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007400 cfgerr++;
7401 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007402#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007403 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007404 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
7405 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007406 cfgerr++;
7407 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007408#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02007409 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007410 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
7411 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007412 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007413 }
7414 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02007415 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007416 /* If no LB algo is set in a backend, and we're not in
7417 * transparent mode, dispatch mode nor proxy mode, we
7418 * want to use balance roundrobin by default.
7419 */
7420 curproxy->lbprm.algo &= ~BE_LB_ALGO;
7421 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007422 }
7423 }
Willy Tarreau193cf932007-09-17 10:17:23 +02007424
Willy Tarreau1620ec32011-08-06 17:05:02 +02007425 if (curproxy->options & PR_O_DISPATCH)
7426 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
7427 else if (curproxy->options & PR_O_HTTP_PROXY)
7428 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
7429 else if (curproxy->options & PR_O_TRANSP)
7430 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01007431
Willy Tarreau1620ec32011-08-06 17:05:02 +02007432 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
7433 if (curproxy->options & PR_O_DISABLE404) {
7434 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7435 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
7436 err_code |= ERR_WARN;
7437 curproxy->options &= ~PR_O_DISABLE404;
7438 }
7439 if (curproxy->options2 & PR_O2_CHK_SNDST) {
7440 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7441 "send-state", proxy_type_str(curproxy), curproxy->id);
7442 err_code |= ERR_WARN;
7443 curproxy->options &= ~PR_O2_CHK_SNDST;
7444 }
Willy Tarreauef781042010-01-27 11:53:01 +01007445 }
7446
Simon Horman98637e52014-06-20 12:30:16 +09007447 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
7448 if (!global.external_check) {
7449 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
7450 curproxy->id, "option external-check");
7451 cfgerr++;
7452 }
7453 if (!curproxy->check_command) {
7454 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
7455 curproxy->id, "option external-check");
7456 cfgerr++;
7457 }
7458 }
7459
Simon Horman64e34162015-02-06 11:11:57 +09007460 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007461 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
7462 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Pieter Baauw8669e972015-08-17 00:45:05 +02007463 "'email-alert from', 'email-alert level' 'email-alert mailers', "
7464 "'email-alert myhostname', or 'email-alert to' "
7465 "requires each of 'email-alert from', 'email-alert mailers' and 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007466 "to be present).\n",
7467 proxy_type_str(curproxy), curproxy->id);
7468 err_code |= ERR_WARN;
7469 free_email_alert(curproxy);
7470 }
7471 if (!curproxy->email_alert.myhostname)
7472 curproxy->email_alert.myhostname = hostname;
Simon Horman9dc49962015-01-30 11:22:59 +09007473 }
7474
Simon Horman98637e52014-06-20 12:30:16 +09007475 if (curproxy->check_command) {
7476 int clear = 0;
7477 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7478 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7479 "external-check command", proxy_type_str(curproxy), curproxy->id);
7480 err_code |= ERR_WARN;
7481 clear = 1;
7482 }
7483 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
Ben Cabot49795eb2015-09-16 12:07:51 +01007484 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-check path' is not set.\n",
Simon Horman98637e52014-06-20 12:30:16 +09007485 curproxy->id, "external-check command");
7486 cfgerr++;
7487 }
7488 if (clear) {
7489 free(curproxy->check_command);
7490 curproxy->check_command = NULL;
7491 }
7492 }
7493
7494 if (curproxy->check_path) {
7495 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7496 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7497 "external-check path", proxy_type_str(curproxy), curproxy->id);
7498 err_code |= ERR_WARN;
7499 free(curproxy->check_path);
7500 curproxy->check_path = NULL;
7501 }
7502 }
7503
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007504 /* if a default backend was specified, let's find it */
7505 if (curproxy->defbe.name) {
7506 struct proxy *target;
7507
Willy Tarreauafb39922015-05-26 12:04:09 +02007508 target = proxy_be_by_name(curproxy->defbe.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007509 if (!target) {
7510 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
7511 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007512 cfgerr++;
7513 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007514 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
7515 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02007516 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007517 } else if (target->mode != curproxy->mode &&
7518 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7519
7520 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) as its default backend (see 'mode').\n",
7521 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7522 curproxy->conf.file, curproxy->conf.line,
7523 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7524 target->conf.file, target->conf.line);
7525 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007526 } else {
7527 free(curproxy->defbe.name);
7528 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01007529
7530 /* Emit a warning if this proxy also has some servers */
7531 if (curproxy->srv) {
7532 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
7533 curproxy->id);
7534 err_code |= ERR_WARN;
7535 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007536 }
7537 }
7538
Willy Tarreau55ea7572007-06-17 19:56:27 +02007539 /* find the target proxy for 'use_backend' rules */
7540 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007541 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007542 struct logformat_node *node;
7543 char *pxname;
7544
7545 /* Try to parse the string as a log format expression. If the result
7546 * of the parsing is only one entry containing a simple string, then
7547 * it's a standard string corresponding to a static rule, thus the
7548 * parsing is cancelled and be.name is restored to be resolved.
7549 */
7550 pxname = rule->be.name;
7551 LIST_INIT(&rule->be.expr);
7552 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
7553 curproxy->conf.args.file, curproxy->conf.args.line);
7554 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
7555
7556 if (!LIST_ISEMPTY(&rule->be.expr)) {
7557 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
7558 rule->dynamic = 1;
7559 free(pxname);
7560 continue;
7561 }
7562 /* simple string: free the expression and fall back to static rule */
7563 free(node->arg);
7564 free(node);
7565 }
7566
7567 rule->dynamic = 0;
7568 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007569
Willy Tarreauafb39922015-05-26 12:04:09 +02007570 target = proxy_be_by_name(rule->be.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007571 if (!target) {
7572 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
7573 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007574 cfgerr++;
7575 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007576 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
7577 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007578 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007579 } else if (target->mode != curproxy->mode &&
7580 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7581
7582 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) in a 'use_backend' rule (see 'mode').\n",
7583 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7584 curproxy->conf.file, curproxy->conf.line,
7585 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7586 target->conf.file, target->conf.line);
7587 cfgerr++;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007588 } else {
7589 free((void *)rule->be.name);
7590 rule->be.backend = target;
7591 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007592 }
7593
Willy Tarreau64ab6072014-09-16 12:17:36 +02007594 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007595 list_for_each_entry(srule, &curproxy->server_rules, list) {
7596 struct server *target = findserver(curproxy, srule->srv.name);
7597
7598 if (!target) {
7599 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7600 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7601 cfgerr++;
7602 continue;
7603 }
7604 free((void *)srule->srv.name);
7605 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007606 }
7607
Emeric Brunb982a3d2010-01-04 15:45:53 +01007608 /* find the target table for 'stick' rules */
7609 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7610 struct proxy *target;
7611
Emeric Brun1d33b292010-01-04 15:47:17 +01007612 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7613 if (mrule->flags & STK_IS_STORE)
7614 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7615
Emeric Brunb982a3d2010-01-04 15:45:53 +01007616 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007617 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007618 else
7619 target = curproxy;
7620
7621 if (!target) {
7622 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7623 curproxy->id, mrule->table.name);
7624 cfgerr++;
7625 }
7626 else if (target->table.size == 0) {
7627 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7628 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7629 cfgerr++;
7630 }
Willy Tarreau12785782012-04-27 21:37:17 +02007631 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7632 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007633 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7634 cfgerr++;
7635 }
7636 else {
7637 free((void *)mrule->table.name);
7638 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007639 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007640 }
7641 }
7642
7643 /* find the target table for 'store response' rules */
7644 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7645 struct proxy *target;
7646
Emeric Brun1d33b292010-01-04 15:47:17 +01007647 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7648
Emeric Brunb982a3d2010-01-04 15:45:53 +01007649 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007650 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007651 else
7652 target = curproxy;
7653
7654 if (!target) {
7655 Alert("Proxy '%s': unable to find store table '%s'.\n",
7656 curproxy->id, mrule->table.name);
7657 cfgerr++;
7658 }
7659 else if (target->table.size == 0) {
7660 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7661 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7662 cfgerr++;
7663 }
Willy Tarreau12785782012-04-27 21:37:17 +02007664 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7665 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007666 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7667 cfgerr++;
7668 }
7669 else {
7670 free((void *)mrule->table.name);
7671 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007672 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007673 }
7674 }
7675
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007676 /* find the target table for 'tcp-request' layer 4 rules */
7677 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
7678 struct proxy *target;
7679
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007680 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007681 continue;
7682
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007683 if (trule->arg.trk_ctr.table.n)
7684 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007685 else
7686 target = curproxy;
7687
7688 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007689 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007690 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007691 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007692 cfgerr++;
7693 }
7694 else if (target->table.size == 0) {
7695 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007696 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007697 cfgerr++;
7698 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007699 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007700 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007701 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007702 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007703 cfgerr++;
7704 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007705 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007706 free(trule->arg.trk_ctr.table.n);
7707 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007708 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007709 * to pass a list of counters to track and allocate them right here using
7710 * stktable_alloc_data_type().
7711 */
7712 }
7713 }
7714
Willy Tarreaud1f96522010-08-03 19:34:32 +02007715 /* find the target table for 'tcp-request' layer 6 rules */
7716 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7717 struct proxy *target;
7718
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007719 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02007720 continue;
7721
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007722 if (trule->arg.trk_ctr.table.n)
7723 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007724 else
7725 target = curproxy;
7726
7727 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007728 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007729 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007730 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02007731 cfgerr++;
7732 }
7733 else if (target->table.size == 0) {
7734 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007735 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007736 cfgerr++;
7737 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007738 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007739 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007740 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007741 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007742 cfgerr++;
7743 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02007744 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007745 free(trule->arg.trk_ctr.table.n);
7746 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007747 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02007748 * to pass a list of counters to track and allocate them right here using
7749 * stktable_alloc_data_type().
7750 */
7751 }
7752 }
7753
Baptiste Assmanne9544932015-11-03 23:31:35 +01007754 /* parse http-request capture rules to ensure id really exists */
7755 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7756 if (hrqrule->action != ACT_CUSTOM ||
7757 hrqrule->action_ptr != http_action_req_capture_by_id)
7758 continue;
7759
7760 if (hrqrule->arg.capid.idx >= curproxy->nb_req_cap) {
7761 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-request capture rule.\n",
7762 curproxy->id, hrqrule->arg.capid.idx);
7763 cfgerr++;
7764 }
7765 }
7766
7767 /* parse http-response capture rules to ensure id really exists */
7768 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
7769 if (hrqrule->action != ACT_CUSTOM ||
7770 hrqrule->action_ptr != http_action_res_capture_by_id)
7771 continue;
7772
7773 if (hrqrule->arg.capid.idx >= curproxy->nb_rsp_cap) {
7774 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-response capture rule.\n",
7775 curproxy->id, hrqrule->arg.capid.idx);
7776 cfgerr++;
7777 }
7778 }
7779
Willy Tarreau09448f72014-06-25 18:12:15 +02007780 /* find the target table for 'http-request' layer 7 rules */
7781 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7782 struct proxy *target;
7783
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007784 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau09448f72014-06-25 18:12:15 +02007785 continue;
7786
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007787 if (hrqrule->arg.trk_ctr.table.n)
7788 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
Willy Tarreau09448f72014-06-25 18:12:15 +02007789 else
7790 target = curproxy;
7791
7792 if (!target) {
7793 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007794 curproxy->id, hrqrule->arg.trk_ctr.table.n,
Willy Tarreau09448f72014-06-25 18:12:15 +02007795 http_req_trk_idx(hrqrule->action));
7796 cfgerr++;
7797 }
7798 else if (target->table.size == 0) {
7799 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007800 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau09448f72014-06-25 18:12:15 +02007801 cfgerr++;
7802 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007803 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau09448f72014-06-25 18:12:15 +02007804 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007805 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau09448f72014-06-25 18:12:15 +02007806 http_req_trk_idx(hrqrule->action));
7807 cfgerr++;
7808 }
7809 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007810 free(hrqrule->arg.trk_ctr.table.n);
7811 hrqrule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau09448f72014-06-25 18:12:15 +02007812 /* Note: if we decide to enhance the track-sc syntax, we may be able
7813 * to pass a list of counters to track and allocate them right here using
7814 * stktable_alloc_data_type().
7815 */
7816 }
7817 }
7818
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02007819 /* move any "block" rules at the beginning of the http-request rules */
7820 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
7821 /* insert block_rules into http_req_rules at the beginning */
7822 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
7823 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
7824 curproxy->block_rules.n->p = &curproxy->http_req_rules;
7825 curproxy->http_req_rules.n = curproxy->block_rules.n;
7826 LIST_INIT(&curproxy->block_rules);
7827 }
7828
Emeric Brun32da3c42010-09-23 18:39:19 +02007829 if (curproxy->table.peers.name) {
7830 struct peers *curpeers = peers;
7831
7832 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
7833 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
7834 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01007835 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02007836 break;
7837 }
7838 }
7839
7840 if (!curpeers) {
7841 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
7842 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007843 free((void *)curproxy->table.peers.name);
7844 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007845 cfgerr++;
7846 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02007847 else if (curpeers->state == PR_STSTOPPED) {
7848 /* silently disable this peers section */
7849 curproxy->table.peers.p = NULL;
7850 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007851 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02007852 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
7853 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007854 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007855 cfgerr++;
7856 }
7857 }
7858
Simon Horman9dc49962015-01-30 11:22:59 +09007859
7860 if (curproxy->email_alert.mailers.name) {
7861 struct mailers *curmailers = mailers;
7862
7863 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
7864 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
7865 free(curproxy->email_alert.mailers.name);
7866 curproxy->email_alert.mailers.m = curmailers;
7867 curmailers->users++;
7868 break;
7869 }
7870 }
7871
7872 if (!curmailers) {
7873 Alert("Proxy '%s': unable to find mailers '%s'.\n",
7874 curproxy->id, curproxy->email_alert.mailers.name);
7875 free_email_alert(curproxy);
7876 cfgerr++;
7877 }
7878 }
7879
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007880 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01007881 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007882 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
7883 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
7884 "proxy", curproxy->id);
7885 cfgerr++;
7886 goto out_uri_auth_compat;
7887 }
7888
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007889 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007890 const char *uri_auth_compat_req[10];
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007891 struct act_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01007892 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007893
Willy Tarreau95fa4692010-02-01 13:05:50 +01007894 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
7895 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007896
7897 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007898 uri_auth_compat_req[i++] = "realm";
7899 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
7900 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007901
Willy Tarreau95fa4692010-02-01 13:05:50 +01007902 uri_auth_compat_req[i++] = "unless";
7903 uri_auth_compat_req[i++] = "{";
7904 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
7905 uri_auth_compat_req[i++] = "}";
7906 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007907
Willy Tarreauff011f22011-01-06 17:51:27 +01007908 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
7909 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007910 cfgerr++;
7911 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007912 }
7913
Willy Tarreauff011f22011-01-06 17:51:27 +01007914 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01007915
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007916 if (curproxy->uri_auth->auth_realm) {
7917 free(curproxy->uri_auth->auth_realm);
7918 curproxy->uri_auth->auth_realm = NULL;
7919 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007920
7921 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007922 }
7923out_uri_auth_compat:
7924
Dragan Dosen43885c72015-10-01 13:18:13 +02007925 /* check whether we have a log server that uses RFC5424 log format */
Dragan Dosen1322d092015-09-22 16:05:32 +02007926 list_for_each_entry(tmplogsrv, &curproxy->logsrvs, list) {
Dragan Dosen43885c72015-10-01 13:18:13 +02007927 if (tmplogsrv->format == LOG_FORMAT_RFC5424) {
7928 if (!curproxy->conf.logformat_sd_string) {
7929 /* set the default logformat_sd_string */
7930 curproxy->conf.logformat_sd_string = default_rfc5424_sd_log_format;
7931 }
Dragan Dosen1322d092015-09-22 16:05:32 +02007932 break;
Dragan Dosen1322d092015-09-22 16:05:32 +02007933 }
Dragan Dosen1322d092015-09-22 16:05:32 +02007934 }
Dragan Dosen68d2e3a2015-09-19 22:35:44 +02007935
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007936 /* compile the log format */
7937 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02007938 if (curproxy->conf.logformat_string != default_http_log_format &&
7939 curproxy->conf.logformat_string != default_tcp_log_format &&
7940 curproxy->conf.logformat_string != clf_http_log_format)
7941 free(curproxy->conf.logformat_string);
7942 curproxy->conf.logformat_string = NULL;
7943 free(curproxy->conf.lfs_file);
7944 curproxy->conf.lfs_file = NULL;
7945 curproxy->conf.lfs_line = 0;
Dragan Dosen0b85ece2015-09-25 19:17:44 +02007946
7947 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
7948 free(curproxy->conf.logformat_sd_string);
7949 curproxy->conf.logformat_sd_string = NULL;
7950 free(curproxy->conf.lfsd_file);
7951 curproxy->conf.lfsd_file = NULL;
7952 curproxy->conf.lfsd_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007953 }
7954
Willy Tarreau62a61232013-04-12 18:13:46 +02007955 if (curproxy->conf.logformat_string) {
7956 curproxy->conf.args.ctx = ARGC_LOG;
7957 curproxy->conf.args.file = curproxy->conf.lfs_file;
7958 curproxy->conf.args.line = curproxy->conf.lfs_line;
7959 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007960 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007961 curproxy->conf.args.file = NULL;
7962 curproxy->conf.args.line = 0;
7963 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007964
Dragan Dosen0b85ece2015-09-25 19:17:44 +02007965 if (curproxy->conf.logformat_sd_string) {
7966 curproxy->conf.args.ctx = ARGC_LOGSD;
7967 curproxy->conf.args.file = curproxy->conf.lfsd_file;
7968 curproxy->conf.args.line = curproxy->conf.lfsd_line;
7969 parse_logformat_string(curproxy->conf.logformat_sd_string, curproxy, &curproxy->logformat_sd, LOG_OPT_MANDATORY,
7970 SMP_VAL_FE_LOG_END, curproxy->conf.lfsd_file, curproxy->conf.lfsd_line);
7971 add_to_logformat_list(NULL, NULL, LF_SEPARATOR, &curproxy->logformat_sd);
7972 curproxy->conf.args.file = NULL;
7973 curproxy->conf.args.line = 0;
7974 }
7975
Willy Tarreau62a61232013-04-12 18:13:46 +02007976 if (curproxy->conf.uniqueid_format_string) {
7977 curproxy->conf.args.ctx = ARGC_UIF;
7978 curproxy->conf.args.file = curproxy->conf.uif_file;
7979 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01007980 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Godbachd9722032014-12-18 15:44:58 +08007981 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007982 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007983 curproxy->conf.args.file = NULL;
7984 curproxy->conf.args.line = 0;
7985 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007986
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007987 /* only now we can check if some args remain unresolved.
7988 * This must be done after the users and groups resolution.
7989 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007990 cfgerr += smp_resolve_args(curproxy);
7991 if (!cfgerr)
7992 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01007993
Willy Tarreau2738a142006-07-08 17:28:09 +02007994 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007995 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02007996 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02007997 (!curproxy->timeout.connect ||
7998 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007999 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02008000 " | While not properly invalid, you will certainly encounter various problems\n"
8001 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01008002 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008003 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008004 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02008005 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02008006
Willy Tarreau1fa31262007-12-03 00:36:16 +01008007 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
8008 * We must still support older configurations, so let's find out whether those
8009 * parameters have been set or must be copied from contimeouts.
8010 */
8011 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008012 if (!curproxy->timeout.tarpit ||
8013 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008014 /* tarpit timeout not set. We search in the following order:
8015 * default.tarpit, curr.connect, default.connect.
8016 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008017 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008018 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008019 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008020 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008021 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008022 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008023 }
8024 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008025 (!curproxy->timeout.queue ||
8026 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008027 /* queue timeout not set. We search in the following order:
8028 * default.queue, curr.connect, default.connect.
8029 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008030 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008031 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008032 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008033 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008034 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008035 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008036 }
8037 }
8038
Willy Tarreau1620ec32011-08-06 17:05:02 +02008039 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01008040 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
8041 curproxy->check_req = (char *)malloc(curproxy->check_len);
8042 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02008043 }
8044
Willy Tarreau215663d2014-06-13 18:30:23 +02008045 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
8046 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
8047 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
8048 proxy_type_str(curproxy), curproxy->id);
8049 err_code |= ERR_WARN;
8050 }
8051
Willy Tarreau193b8c62012-11-22 00:17:38 +01008052 /* ensure that cookie capture length is not too large */
8053 if (curproxy->capture_len >= global.tune.cookie_len) {
8054 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
8055 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
8056 err_code |= ERR_WARN;
8057 curproxy->capture_len = global.tune.cookie_len - 1;
8058 }
8059
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008060 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01008061 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008062 curproxy->req_cap_pool = create_pool("ptrcap",
8063 curproxy->nb_req_cap * sizeof(char *),
8064 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008065 }
8066
8067 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008068 curproxy->rsp_cap_pool = create_pool("ptrcap",
8069 curproxy->nb_rsp_cap * sizeof(char *),
8070 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008071 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008072
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02008073 switch (curproxy->load_server_state_from_file) {
8074 case PR_SRV_STATE_FILE_UNSPEC:
8075 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
8076 break;
8077 case PR_SRV_STATE_FILE_GLOBAL:
8078 if (!global.server_state_file) {
8079 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",
8080 curproxy->id);
8081 err_code |= ERR_WARN;
8082 }
8083 break;
8084 }
8085
Willy Tarreaubaaee002006-06-26 02:48:02 +02008086 /* first, we will invert the servers list order */
8087 newsrv = NULL;
8088 while (curproxy->srv) {
8089 struct server *next;
8090
8091 next = curproxy->srv->next;
8092 curproxy->srv->next = newsrv;
8093 newsrv = curproxy->srv;
8094 if (!next)
8095 break;
8096 curproxy->srv = next;
8097 }
8098
Willy Tarreau17edc812014-01-03 12:14:34 +01008099 /* Check that no server name conflicts. This causes trouble in the stats.
8100 * We only emit a warning for the first conflict affecting each server,
8101 * in order to avoid combinatory explosion if all servers have the same
8102 * name. We do that only for servers which do not have an explicit ID,
8103 * because these IDs were made also for distinguishing them and we don't
8104 * want to annoy people who correctly manage them.
8105 */
8106 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
8107 struct server *other_srv;
8108
8109 if (newsrv->puid)
8110 continue;
8111
8112 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
8113 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
8114 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
8115 newsrv->conf.file, newsrv->conf.line,
8116 proxy_type_str(curproxy), curproxy->id,
8117 newsrv->id, other_srv->conf.line);
8118 break;
8119 }
8120 }
8121 }
8122
Willy Tarreaudd701652010-05-25 23:03:02 +02008123 /* assign automatic UIDs to servers which don't have one yet */
8124 next_id = 1;
8125 newsrv = curproxy->srv;
8126 while (newsrv != NULL) {
8127 if (!newsrv->puid) {
8128 /* server ID not set, use automatic numbering with first
8129 * spare entry starting with next_svid.
8130 */
8131 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
8132 newsrv->conf.id.key = newsrv->puid = next_id;
8133 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
8134 }
8135 next_id++;
8136 newsrv = newsrv->next;
8137 }
8138
Willy Tarreau20697042007-11-15 23:26:18 +01008139 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01008140 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02008141
Willy Tarreau62c3be22012-01-20 13:12:32 +01008142 /*
8143 * If this server supports a maxconn parameter, it needs a dedicated
8144 * tasks to fill the emptied slots when a connection leaves.
8145 * Also, resolve deferred tracking dependency if needed.
8146 */
8147 newsrv = curproxy->srv;
8148 while (newsrv != NULL) {
8149 if (newsrv->minconn > newsrv->maxconn) {
8150 /* Only 'minconn' was specified, or it was higher than or equal
8151 * to 'maxconn'. Let's turn this into maxconn and clean it, as
8152 * this will avoid further useless expensive computations.
8153 */
8154 newsrv->maxconn = newsrv->minconn;
8155 } else if (newsrv->maxconn && !newsrv->minconn) {
8156 /* minconn was not specified, so we set it to maxconn */
8157 newsrv->minconn = newsrv->maxconn;
8158 }
8159
Emeric Brun01f8e2f2012-05-18 16:02:00 +02008160#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02008161 if (newsrv->use_ssl || newsrv->check.use_ssl)
8162 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02008163#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02008164
Willy Tarreau2f075e92013-12-03 11:11:34 +01008165 /* set the check type on the server */
8166 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
8167
Willy Tarreau62c3be22012-01-20 13:12:32 +01008168 if (newsrv->trackit) {
8169 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02008170 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008171 char *pname, *sname;
8172
8173 pname = newsrv->trackit;
8174 sname = strrchr(pname, '/');
8175
8176 if (sname)
8177 *sname++ = '\0';
8178 else {
8179 sname = pname;
8180 pname = NULL;
8181 }
8182
8183 if (pname) {
Willy Tarreau9e0bb102015-05-26 11:24:42 +02008184 px = proxy_be_by_name(pname);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008185 if (!px) {
8186 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
8187 proxy_type_str(curproxy), curproxy->id,
8188 newsrv->id, pname);
8189 cfgerr++;
8190 goto next_srv;
8191 }
8192 } else
8193 px = curproxy;
8194
8195 srv = findserver(px, sname);
8196 if (!srv) {
8197 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
8198 proxy_type_str(curproxy), curproxy->id,
8199 newsrv->id, sname);
8200 cfgerr++;
8201 goto next_srv;
8202 }
8203
Willy Tarreau32091232014-05-16 13:52:00 +02008204 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
8205 !(srv->agent.state & CHK_ST_CONFIGURED) &&
8206 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01008207 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02008208 "tracking as it does not have any check nor agent enabled.\n",
8209 proxy_type_str(curproxy), curproxy->id,
8210 newsrv->id, px->id, srv->id);
8211 cfgerr++;
8212 goto next_srv;
8213 }
8214
8215 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
8216
8217 if (loop) {
8218 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
8219 "belongs to a tracking chain looping back to %s/%s.\n",
8220 proxy_type_str(curproxy), curproxy->id,
8221 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008222 cfgerr++;
8223 goto next_srv;
8224 }
8225
8226 if (curproxy != px &&
8227 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
8228 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
8229 "tracking: disable-on-404 option inconsistency.\n",
8230 proxy_type_str(curproxy), curproxy->id,
8231 newsrv->id, px->id, srv->id);
8232 cfgerr++;
8233 goto next_srv;
8234 }
8235
8236 /* if the other server is forced disabled, we have to do the same here */
Willy Tarreau20125212014-05-13 19:44:56 +02008237 if (srv->admin & SRV_ADMF_MAINT) {
Willy Tarreaua0066dd2014-05-16 11:25:16 +02008238 newsrv->admin |= SRV_ADMF_IMAINT;
Willy Tarreau892337c2014-05-13 23:41:20 +02008239 newsrv->state = SRV_ST_STOPPED;
Simon Horman125d0992013-02-24 17:23:38 +09008240 newsrv->check.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008241 }
8242
8243 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01008244 newsrv->tracknext = srv->trackers;
8245 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008246
8247 free(newsrv->trackit);
8248 newsrv->trackit = NULL;
8249 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008250
8251 /*
8252 * resolve server's resolvers name and update the resolvers pointer
8253 * accordingly
8254 */
8255 if (newsrv->resolvers_id) {
8256 struct dns_resolvers *curr_resolvers;
8257 int found;
8258
8259 found = 0;
8260 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
8261 if (!strcmp(curr_resolvers->id, newsrv->resolvers_id)) {
8262 found = 1;
8263 break;
8264 }
8265 }
8266
8267 if (!found) {
8268 Alert("config : %s '%s', server '%s': unable to find required resolvers '%s'\n",
8269 proxy_type_str(curproxy), curproxy->id,
8270 newsrv->id, newsrv->resolvers_id);
8271 cfgerr++;
8272 } else {
8273 free(newsrv->resolvers_id);
8274 newsrv->resolvers_id = NULL;
8275 if (newsrv->resolution)
8276 newsrv->resolution->resolvers = curr_resolvers;
8277 }
8278 }
8279 else {
8280 /* if no resolvers section associated to this server
8281 * we can clean up the associated resolution structure
8282 */
8283 if (newsrv->resolution) {
8284 free(newsrv->resolution->hostname_dn);
8285 newsrv->resolution->hostname_dn = NULL;
8286 free(newsrv->resolution);
8287 newsrv->resolution = NULL;
8288 }
8289 }
8290
Willy Tarreau62c3be22012-01-20 13:12:32 +01008291 next_srv:
8292 newsrv = newsrv->next;
8293 }
8294
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008295 /* We have to initialize the server lookup mechanism depending
8296 * on what LB algorithm was choosen.
8297 */
8298
8299 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
8300 switch (curproxy->lbprm.algo & BE_LB_KIND) {
8301 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02008302 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
8303 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8304 init_server_map(curproxy);
8305 } else {
8306 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
8307 fwrr_init_server_groups(curproxy);
8308 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008309 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008310
Willy Tarreau3ebb1162012-02-13 16:57:44 +01008311 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01008312 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
8313 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
8314 fwlc_init_server_tree(curproxy);
8315 } else {
8316 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
8317 fas_init_server_tree(curproxy);
8318 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008319 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008320
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008321 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008322 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
8323 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
8324 chash_init_server_tree(curproxy);
8325 } else {
8326 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8327 init_server_map(curproxy);
8328 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008329 break;
8330 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02008331
8332 if (curproxy->options & PR_O_LOGASAP)
8333 curproxy->to_log &= ~LW_BYTES;
8334
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008335 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008336 (curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->logsrvs) &&
8337 (!LIST_ISEMPTY(&curproxy->logformat) || !LIST_ISEMPTY(&curproxy->logformat_sd))) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008338 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
8339 proxy_type_str(curproxy), curproxy->id);
8340 err_code |= ERR_WARN;
8341 }
8342
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008343 if (curproxy->mode != PR_MODE_HTTP) {
8344 int optnum;
8345
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008346 if (curproxy->uri_auth) {
8347 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
8348 proxy_type_str(curproxy), curproxy->id);
8349 err_code |= ERR_WARN;
8350 curproxy->uri_auth = NULL;
8351 }
8352
Willy Tarreau87cf5142011-08-19 22:57:24 +02008353 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008354 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8355 "forwardfor", proxy_type_str(curproxy), curproxy->id);
8356 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02008357 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008358 }
8359
8360 if (curproxy->options & PR_O_ORGTO) {
8361 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8362 "originalto", proxy_type_str(curproxy), curproxy->id);
8363 err_code |= ERR_WARN;
8364 curproxy->options &= ~PR_O_ORGTO;
8365 }
8366
8367 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
8368 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
8369 (curproxy->cap & cfg_opts[optnum].cap) &&
8370 (curproxy->options & cfg_opts[optnum].val)) {
8371 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8372 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
8373 err_code |= ERR_WARN;
8374 curproxy->options &= ~cfg_opts[optnum].val;
8375 }
8376 }
8377
8378 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
8379 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
8380 (curproxy->cap & cfg_opts2[optnum].cap) &&
8381 (curproxy->options2 & cfg_opts2[optnum].val)) {
8382 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8383 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
8384 err_code |= ERR_WARN;
8385 curproxy->options2 &= ~cfg_opts2[optnum].val;
8386 }
8387 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008388
Willy Tarreau29fbe512015-08-20 19:35:14 +02008389#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008390 if (curproxy->conn_src.bind_hdr_occ) {
8391 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008392 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01008393 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008394 err_code |= ERR_WARN;
8395 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008396#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008397 }
8398
Willy Tarreaubaaee002006-06-26 02:48:02 +02008399 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01008400 * ensure that we're not cross-dressing a TCP server into HTTP.
8401 */
8402 newsrv = curproxy->srv;
8403 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01008404 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008405 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
8406 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008407 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01008408 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008409
Willy Tarreau0cec3312011-10-31 13:49:26 +01008410 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
8411 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
8412 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8413 err_code |= ERR_WARN;
8414 }
8415
Willy Tarreauc93cd162014-05-13 15:54:22 +02008416 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02008417 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
8418 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8419 err_code |= ERR_WARN;
8420 }
8421
Willy Tarreau29fbe512015-08-20 19:35:14 +02008422#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008423 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
8424 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008425 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 +01008426 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008427 err_code |= ERR_WARN;
8428 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008429#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01008430 newsrv = newsrv->next;
8431 }
8432
Willy Tarreaue42bd962014-09-16 16:21:19 +02008433 /* check if we have a frontend with "tcp-request content" looking at L7
8434 * with no inspect-delay
8435 */
8436 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
8437 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008438 if (trule->action == ACT_TCP_CAPTURE &&
Thierry FOURNIERd0d65ae2015-08-04 08:21:12 +02008439 !(trule->arg.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008440 break;
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008441 if ((trule->action >= ACT_ACTION_TRK_SC0 && trule->action <= ACT_ACTION_TRK_SCMAX) &&
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008442 !(trule->arg.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008443 break;
8444 }
8445
8446 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
8447 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
8448 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
8449 " This means that these rules will randomly find their contents. This can be fixed by"
8450 " setting the tcp-request inspect-delay.\n",
8451 proxy_type_str(curproxy), curproxy->id);
8452 err_code |= ERR_WARN;
8453 }
8454 }
8455
Willy Tarreauc1a21672009-08-16 22:37:44 +02008456 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02008457 if (!curproxy->accept)
8458 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02008459
Willy Tarreauc1a21672009-08-16 22:37:44 +02008460 if (curproxy->tcp_req.inspect_delay ||
8461 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02008462 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008463
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008464 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008465 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008466 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008467 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008468
8469 /* both TCP and HTTP must check switching rules */
8470 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
8471 }
8472
8473 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02008474 if (curproxy->tcp_req.inspect_delay ||
8475 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
8476 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
8477
Emeric Brun97679e72010-09-23 17:56:44 +02008478 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
8479 curproxy->be_rsp_ana |= AN_RES_INSPECT;
8480
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008481 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008482 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008483 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008484 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008485
8486 /* If the backend does requires RDP cookie persistence, we have to
8487 * enable the corresponding analyser.
8488 */
8489 if (curproxy->options2 & PR_O2_RDPC_PRST)
8490 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
8491 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008492 }
8493
8494 /***********************************************************/
8495 /* At this point, target names have already been resolved. */
8496 /***********************************************************/
8497
8498 /* Check multi-process mode compatibility */
8499
8500 if (global.nbproc > 1 && global.stats_fe) {
8501 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8502 unsigned long mask;
8503
8504 mask = nbits(global.nbproc);
8505 if (global.stats_fe->bind_proc)
8506 mask &= global.stats_fe->bind_proc;
8507
8508 if (bind_conf->bind_proc)
8509 mask &= bind_conf->bind_proc;
8510
8511 /* stop here if more than one process is used */
David Carliere6c39412015-07-02 07:00:17 +00008512 if (my_popcountl(mask) > 1)
Willy Tarreau419ead82014-09-16 13:41:21 +02008513 break;
8514 }
8515 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
8516 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");
8517 }
8518 }
8519
8520 /* Make each frontend inherit bind-process from its listeners when not specified. */
8521 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8522 if (curproxy->bind_proc)
8523 continue;
8524
8525 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8526 unsigned long mask;
8527
Willy Tarreaue428b082015-05-04 21:57:58 +02008528 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008529 curproxy->bind_proc |= mask;
8530 }
8531
8532 if (!curproxy->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008533 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008534 }
8535
8536 if (global.stats_fe) {
8537 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8538 unsigned long mask;
8539
Willy Tarreaue428b082015-05-04 21:57:58 +02008540 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008541 global.stats_fe->bind_proc |= mask;
8542 }
8543 if (!global.stats_fe->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008544 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008545 }
8546
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02008547 /* propagate bindings from frontends to backends. Don't do it if there
8548 * are any fatal errors as we must not call it with unresolved proxies.
8549 */
8550 if (!cfgerr) {
8551 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8552 if (curproxy->cap & PR_CAP_FE)
8553 propagate_processes(curproxy, NULL);
8554 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008555 }
8556
8557 /* Bind each unbound backend to all processes when not specified. */
8558 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8559 if (curproxy->bind_proc)
8560 continue;
Willy Tarreaue428b082015-05-04 21:57:58 +02008561 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008562 }
8563
8564 /*******************************************************/
8565 /* At this step, all proxies have a non-null bind_proc */
8566 /*******************************************************/
8567
8568 /* perform the final checks before creating tasks */
8569
8570 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8571 struct listener *listener;
8572 unsigned int next_id;
8573 int nbproc;
8574
David Carliere6c39412015-07-02 07:00:17 +00008575 nbproc = my_popcountl(curproxy->bind_proc & nbits(global.nbproc));
Willy Tarreauc1a21672009-08-16 22:37:44 +02008576
Emeric Brunc52962f2012-11-15 18:28:02 +01008577#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008578 /* Configure SSL for each bind line.
8579 * Note: if configuration fails at some point, the ->ctx member
8580 * remains NULL so that listeners can later detach.
8581 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008582 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008583 int alloc_ctx;
8584
Emeric Brunc52962f2012-11-15 18:28:02 +01008585 if (!bind_conf->is_ssl) {
8586 if (bind_conf->default_ctx) {
8587 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
8588 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
8589 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008590 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01008591 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008592 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02008593 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008594 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008595 cfgerr++;
8596 continue;
8597 }
8598
Emeric Brun8dc60392014-05-09 13:52:00 +02008599 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008600 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02008601 if (alloc_ctx == SHCTX_E_INIT_LOCK)
8602 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");
8603 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008604 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02008605 cfgerr++;
8606 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008607 }
8608
Emeric Brunfc0421f2012-09-07 17:30:07 +02008609 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008610 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008611
8612 /* initialize CA variables if the certificates generation is enabled */
8613 cfgerr += ssl_sock_load_ca(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008614 }
Emeric Brunc52962f2012-11-15 18:28:02 +01008615#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008616
Willy Tarreaue6b98942007-10-29 01:09:36 +01008617 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008618 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008619 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008620 if (!listener->luid) {
8621 /* listener ID not set, use automatic numbering with first
8622 * spare entry starting with next_luid.
8623 */
8624 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
8625 listener->conf.id.key = listener->luid = next_id;
8626 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008627 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01008628 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008629
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008630 /* enable separate counters */
8631 if (curproxy->options2 & PR_O2_SOCKSTAT) {
8632 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01008633 if (!listener->name)
8634 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008635 }
Willy Tarreau81796be2012-09-22 19:11:47 +02008636
Willy Tarreaue6b98942007-10-29 01:09:36 +01008637 if (curproxy->options & PR_O_TCP_NOLING)
8638 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02008639 if (!listener->maxconn)
8640 listener->maxconn = curproxy->maxconn;
8641 if (!listener->backlog)
8642 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01008643 if (!listener->maxaccept)
8644 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
8645
8646 /* we want to have an optimal behaviour on single process mode to
8647 * maximize the work at once, but in multi-process we want to keep
8648 * some fairness between processes, so we target half of the max
8649 * number of events to be balanced over all the processes the proxy
8650 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
8651 * used to disable the limit.
8652 */
8653 if (listener->maxaccept > 0) {
8654 if (nbproc > 1)
8655 listener->maxaccept = (listener->maxaccept + 1) / 2;
8656 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
8657 }
8658
Willy Tarreau9903f0e2015-04-04 18:50:31 +02008659 listener->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02008660 listener->handler = process_stream;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008661 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01008662 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01008663
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008664 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
8665 listener->options |= LI_O_TCP_RULES;
8666
Willy Tarreaude3041d2010-05-31 10:56:17 +02008667 if (curproxy->mon_mask.s_addr)
8668 listener->options |= LI_O_CHK_MONNET;
8669
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008670 /* smart accept mode is automatic in HTTP mode */
8671 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008672 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008673 !(curproxy->no_options2 & PR_O2_SMARTACC)))
8674 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01008675 }
8676
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008677 /* Release unused SSL configs */
8678 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8679 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008680 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008681#ifdef USE_OPENSSL
Christopher Faulet31af49d2015-06-09 17:29:50 +02008682 ssl_sock_free_ca(bind_conf);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008683 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008684 free(bind_conf->ca_file);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008685 free(bind_conf->ca_sign_file);
8686 free(bind_conf->ca_sign_pass);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008687 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02008688 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008689 free(bind_conf->crl_file);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008690 if(bind_conf->keys_ref) {
8691 free(bind_conf->keys_ref->filename);
8692 free(bind_conf->keys_ref->tlskeys);
8693 free(bind_conf->keys_ref);
8694 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008695#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008696 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008697
Willy Tarreau102df612014-05-07 23:56:38 +02008698 if (nbproc > 1) {
8699 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02008700 int count, maxproc = 0;
8701
8702 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
David Carliere6c39412015-07-02 07:00:17 +00008703 count = my_popcountl(bind_conf->bind_proc);
Willy Tarreaueb791e02014-09-16 15:11:04 +02008704 if (count > maxproc)
8705 maxproc = count;
8706 }
8707 /* backends have 0, frontends have 1 or more */
8708 if (maxproc != 1)
8709 Warning("Proxy '%s': in multi-process mode, stats will be"
8710 " limited to process assigned to the current request.\n",
8711 curproxy->id);
8712
Willy Tarreau102df612014-05-07 23:56:38 +02008713 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
8714 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
8715 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008716 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008717 }
Willy Tarreau102df612014-05-07 23:56:38 +02008718 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
8719 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
8720 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008721 }
8722 }
Willy Tarreau918ff602011-07-25 16:33:49 +02008723
8724 /* create the task associated with the proxy */
8725 curproxy->task = task_new();
8726 if (curproxy->task) {
8727 curproxy->task->context = curproxy;
8728 curproxy->task->process = manage_proxy;
8729 /* no need to queue, it will be done automatically if some
8730 * listener gets limited.
8731 */
8732 curproxy->task->expire = TICK_ETERNITY;
8733 } else {
8734 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
8735 curproxy->id);
8736 cfgerr++;
8737 }
Willy Tarreaub369a042014-09-16 13:21:03 +02008738 }
8739
Willy Tarreaufbb78422011-06-05 15:38:35 +02008740 /* automatically compute fullconn if not set. We must not do it in the
8741 * loop above because cross-references are not yet fully resolved.
8742 */
8743 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8744 /* If <fullconn> is not set, let's set it to 10% of the sum of
8745 * the possible incoming frontend's maxconns.
8746 */
8747 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
8748 struct proxy *fe;
8749 int total = 0;
8750
8751 /* sum up the number of maxconns of frontends which
8752 * reference this backend at least once or which are
8753 * the same one ('listen').
8754 */
8755 for (fe = proxy; fe; fe = fe->next) {
8756 struct switching_rule *rule;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008757 int found = 0;
8758
8759 if (!(fe->cap & PR_CAP_FE))
8760 continue;
8761
8762 if (fe == curproxy) /* we're on a "listen" instance */
8763 found = 1;
8764
8765 if (fe->defbe.be == curproxy) /* "default_backend" */
8766 found = 1;
8767
8768 /* check if a "use_backend" rule matches */
8769 if (!found) {
8770 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01008771 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02008772 found = 1;
8773 break;
8774 }
8775 }
8776 }
8777
Willy Tarreaufbb78422011-06-05 15:38:35 +02008778 /* now we've checked all possible ways to reference a backend
8779 * from a frontend.
8780 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02008781 if (!found)
8782 continue;
8783 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008784 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02008785 /* we have the sum of the maxconns in <total>. We only
8786 * keep 10% of that sum to set the default fullconn, with
8787 * a hard minimum of 1 (to avoid a divide by zero).
8788 */
8789 curproxy->fullconn = (total + 9) / 10;
8790 if (!curproxy->fullconn)
8791 curproxy->fullconn = 1;
8792 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01008793 }
8794
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008795 /*
8796 * Recount currently required checks.
8797 */
8798
8799 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
8800 int optnum;
8801
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008802 for (optnum = 0; cfg_opts[optnum].name; optnum++)
8803 if (curproxy->options & cfg_opts[optnum].val)
8804 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008805
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008806 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
8807 if (curproxy->options2 & cfg_opts2[optnum].val)
8808 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008809 }
8810
Willy Tarreau0fca4832015-05-01 19:12:05 +02008811 /* compute the required process bindings for the peers */
8812 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
8813 if (curproxy->table.peers.p)
8814 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
8815
Willy Tarreau122541c2011-09-07 21:24:49 +02008816 if (peers) {
8817 struct peers *curpeers = peers, **last;
8818 struct peer *p, *pb;
8819
Willy Tarreau1e273012015-05-01 19:15:17 +02008820 /* Remove all peers sections which don't have a valid listener,
8821 * which are not used by any table, or which are bound to more
8822 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02008823 */
8824 last = &peers;
8825 while (*last) {
8826 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008827
8828 if (curpeers->state == PR_STSTOPPED) {
8829 /* the "disabled" keyword was present */
8830 if (curpeers->peers_fe)
8831 stop_proxy(curpeers->peers_fe);
8832 curpeers->peers_fe = NULL;
8833 }
8834 else if (!curpeers->peers_fe) {
8835 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
8836 curpeers->id, localpeer);
8837 }
David Carliere6c39412015-07-02 07:00:17 +00008838 else if (my_popcountl(curpeers->peers_fe->bind_proc) != 1) {
Willy Tarreau1e273012015-05-01 19:15:17 +02008839 /* either it's totally stopped or too much used */
8840 if (curpeers->peers_fe->bind_proc) {
8841 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreau64c57222015-05-04 21:48:51 +02008842 "running in different processes (%d different ones). "
8843 "Check global.nbproc and all tables' bind-process "
David Carliere6c39412015-07-02 07:00:17 +00008844 "settings.\n", curpeers->id, my_popcountl(curpeers->peers_fe->bind_proc));
Willy Tarreau1e273012015-05-01 19:15:17 +02008845 cfgerr++;
8846 }
8847 stop_proxy(curpeers->peers_fe);
8848 curpeers->peers_fe = NULL;
8849 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008850 else {
Emeric Brunb3971ab2015-05-12 18:49:09 +02008851 peers_init_sync(curpeers);
Willy Tarreau122541c2011-09-07 21:24:49 +02008852 last = &curpeers->next;
8853 continue;
8854 }
8855
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008856 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02008857 p = curpeers->remote;
8858 while (p) {
8859 pb = p->next;
8860 free(p->id);
8861 free(p);
8862 p = pb;
8863 }
8864
8865 /* Destroy and unlink this curpeers section.
8866 * Note: curpeers is backed up into *last.
8867 */
8868 free(curpeers->id);
8869 curpeers = curpeers->next;
8870 free(*last);
8871 *last = curpeers;
8872 }
8873 }
8874
Willy Tarreau6866f3f2015-05-01 19:09:08 +02008875 /* initialize stick-tables on backend capable proxies. This must not
8876 * be done earlier because the data size may be discovered while parsing
8877 * other proxies.
8878 */
8879 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8880 if (curproxy->state == PR_STSTOPPED)
8881 continue;
8882
8883 if (!stktable_init(&curproxy->table)) {
8884 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
8885 cfgerr++;
8886 }
8887 }
8888
Simon Horman0d16a402015-01-30 11:22:58 +09008889 if (mailers) {
8890 struct mailers *curmailers = mailers, **last;
8891 struct mailer *m, *mb;
8892
8893 /* Remove all mailers sections which don't have a valid listener.
8894 * This can happen when a mailers section is never referenced.
8895 */
8896 last = &mailers;
8897 while (*last) {
8898 curmailers = *last;
8899 if (curmailers->users) {
8900 last = &curmailers->next;
8901 continue;
8902 }
8903
8904 Warning("Removing incomplete section 'mailers %s'.\n",
8905 curmailers->id);
8906
8907 m = curmailers->mailer_list;
8908 while (m) {
8909 mb = m->next;
8910 free(m->id);
8911 free(m);
8912 m = mb;
8913 }
8914
8915 /* Destroy and unlink this curmailers section.
8916 * Note: curmailers is backed up into *last.
8917 */
8918 free(curmailers->id);
8919 curmailers = curmailers->next;
8920 free(*last);
8921 *last = curmailers;
8922 }
8923 }
8924
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02008925 /* Update server_state_file_name to backend name if backend is supposed to use
8926 * a server-state file locally defined and none has been provided */
8927 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8928 if (curproxy->load_server_state_from_file == PR_SRV_STATE_FILE_LOCAL &&
8929 curproxy->server_state_file_name == NULL)
8930 curproxy->server_state_file_name = strdup(curproxy->id);
8931 }
8932
Willy Tarreau34eb6712011-10-24 18:15:04 +02008933 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02008934 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02008935 MEM_F_SHARED);
8936
Willy Tarreaubb925012009-07-23 13:36:36 +02008937 if (cfgerr > 0)
8938 err_code |= ERR_ALERT | ERR_FATAL;
8939 out:
8940 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02008941}
8942
Willy Tarreau5b2c3362008-07-09 19:39:06 +02008943/*
8944 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
8945 * parsing sessions.
8946 */
8947void cfg_register_keywords(struct cfg_kw_list *kwl)
8948{
8949 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
8950}
Willy Tarreaubaaee002006-06-26 02:48:02 +02008951
Willy Tarreau5b2c3362008-07-09 19:39:06 +02008952/*
8953 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
8954 */
8955void cfg_unregister_keywords(struct cfg_kw_list *kwl)
8956{
8957 LIST_DEL(&kwl->list);
8958 LIST_INIT(&kwl->list);
8959}
Willy Tarreaubaaee002006-06-26 02:48:02 +02008960
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01008961/* this function register new section in the haproxy configuration file.
8962 * <section_name> is the name of this new section and <section_parser>
8963 * is the called parser. If two section declaration have the same name,
8964 * only the first declared is used.
8965 */
8966int cfg_register_section(char *section_name,
8967 int (*section_parser)(const char *, int, char **, int))
8968{
8969 struct cfg_section *cs;
8970
8971 cs = calloc(1, sizeof(*cs));
8972 if (!cs) {
8973 Alert("register section '%s': out of memory.\n", section_name);
8974 return 0;
8975 }
8976
8977 cs->section_name = section_name;
8978 cs->section_parser = section_parser;
8979
8980 LIST_ADDQ(&sections, &cs->list);
8981
8982 return 1;
8983}
8984
Willy Tarreaubaaee002006-06-26 02:48:02 +02008985/*
David Carlier845efb52015-09-25 11:49:18 +01008986 * free all config section entries
8987 */
8988void cfg_unregister_sections(void)
8989{
8990 struct cfg_section *cs, *ics;
8991
8992 list_for_each_entry_safe(cs, ics, &sections, list) {
8993 LIST_DEL(&cs->list);
8994 free(cs);
8995 }
8996}
8997
8998/*
Willy Tarreaubaaee002006-06-26 02:48:02 +02008999 * Local variables:
9000 * c-indent-level: 8
9001 * c-basic-offset: 8
9002 * End:
9003 */