blob: efbf10dd52ec69ae511fb0d4a1b30ae980d6276d [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 }
Willy Tarreaub22fc302015-12-14 12:04:35 +0100710 else if (!strcmp(args[0], "tune.recv_enough")) {
711 if (alertif_too_many_args(1, file, linenum, args, &err_code))
712 goto out;
713 if (*(args[1]) == 0) {
714 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
715 err_code |= ERR_ALERT | ERR_FATAL;
716 goto out;
717 }
718 global.tune.recv_enough = atol(args[1]);
719 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200720#ifdef USE_OPENSSL
Emeric Brun8dc60392014-05-09 13:52:00 +0200721 else if (!strcmp(args[0], "tune.ssl.force-private-cache")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200722 if (alertif_too_many_args(0, file, linenum, args, &err_code))
723 goto out;
Emeric Brun8dc60392014-05-09 13:52:00 +0200724 global.tune.sslprivatecache = 1;
725 }
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100726 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200727 if (alertif_too_many_args(1, file, linenum, args, &err_code))
728 goto out;
Emeric Brunfc32aca2012-09-03 12:10:29 +0200729 if (*(args[1]) == 0) {
730 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
731 err_code |= ERR_ALERT | ERR_FATAL;
732 goto out;
733 }
734 global.tune.sslcachesize = atol(args[1]);
735 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100736 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
737 unsigned int ssllifetime;
738 const char *res;
739
William Lallemand1a748ae2015-05-19 16:37:23 +0200740 if (alertif_too_many_args(1, file, linenum, args, &err_code))
741 goto out;
Emeric Brun4f65bff2012-11-16 15:11:00 +0100742 if (*(args[1]) == 0) {
743 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
744 err_code |= ERR_ALERT | ERR_FATAL;
745 goto out;
746 }
747
748 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
749 if (res) {
750 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
751 file, linenum, *res, args[0]);
752 err_code |= ERR_ALERT | ERR_FATAL;
753 goto out;
754 }
755
756 global.tune.ssllifetime = ssllifetime;
757 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100758 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200759 if (alertif_too_many_args(1, file, linenum, args, &err_code))
760 goto out;
Willy Tarreaubfd59462013-02-21 07:46:09 +0100761 if (*(args[1]) == 0) {
762 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
763 err_code |= ERR_ALERT | ERR_FATAL;
764 goto out;
765 }
766 global.tune.ssl_max_record = atol(args[1]);
767 }
Remi Gacogne47783ef2015-05-29 15:53:22 +0200768#ifndef OPENSSL_NO_DH
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200769 else if (!strcmp(args[0], "tune.ssl.default-dh-param")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200770 if (alertif_too_many_args(1, file, linenum, args, &err_code))
771 goto out;
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200772 if (*(args[1]) == 0) {
773 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
774 err_code |= ERR_ALERT | ERR_FATAL;
775 goto out;
776 }
777 global.tune.ssl_default_dh_param = atol(args[1]);
778 if (global.tune.ssl_default_dh_param < 1024) {
779 Alert("parsing [%s:%d] : '%s' expects a value >= 1024.\n", file, linenum, args[0]);
780 err_code |= ERR_ALERT | ERR_FATAL;
781 goto out;
782 }
783 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200784#endif
Christopher Faulet31af49d2015-06-09 17:29:50 +0200785 else if (!strcmp(args[0], "tune.ssl.ssl-ctx-cache-size")) {
786 if (alertif_too_many_args(1, file, linenum, args, &err_code))
787 goto out;
788 if (*(args[1]) == 0) {
789 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
790 err_code |= ERR_ALERT | ERR_FATAL;
791 goto out;
792 }
793 global.tune.ssl_ctx_cache = atoi(args[1]);
794 if (global.tune.ssl_ctx_cache < 0) {
795 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
796 file, linenum, args[0]);
797 err_code |= ERR_ALERT | ERR_FATAL;
798 goto out;
799 }
800 }
Remi Gacogne47783ef2015-05-29 15:53:22 +0200801#endif
Willy Tarreau33cb0652014-12-23 22:52:37 +0100802 else if (!strcmp(args[0], "tune.buffers.limit")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200803 if (alertif_too_many_args(1, file, linenum, args, &err_code))
804 goto out;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100805 if (*(args[1]) == 0) {
806 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
807 err_code |= ERR_ALERT | ERR_FATAL;
808 goto out;
809 }
810 global.tune.buf_limit = atol(args[1]);
811 if (global.tune.buf_limit) {
812 if (global.tune.buf_limit < 3)
813 global.tune.buf_limit = 3;
814 if (global.tune.buf_limit <= global.tune.reserved_bufs)
815 global.tune.buf_limit = global.tune.reserved_bufs + 1;
816 }
817 }
Willy Tarreau1058ae72014-12-23 22:40:40 +0100818 else if (!strcmp(args[0], "tune.buffers.reserve")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200819 if (alertif_too_many_args(1, file, linenum, args, &err_code))
820 goto out;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100821 if (*(args[1]) == 0) {
822 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
823 err_code |= ERR_ALERT | ERR_FATAL;
824 goto out;
825 }
826 global.tune.reserved_bufs = atol(args[1]);
827 if (global.tune.reserved_bufs < 2)
828 global.tune.reserved_bufs = 2;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100829 if (global.tune.buf_limit && global.tune.buf_limit <= global.tune.reserved_bufs)
830 global.tune.buf_limit = global.tune.reserved_bufs + 1;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100831 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200832 else if (!strcmp(args[0], "tune.bufsize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200833 if (alertif_too_many_args(1, file, linenum, args, &err_code))
834 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200835 if (*(args[1]) == 0) {
836 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
837 err_code |= ERR_ALERT | ERR_FATAL;
838 goto out;
839 }
840 global.tune.bufsize = atol(args[1]);
Willy Tarreau9b694542015-09-28 13:49:53 +0200841 if (global.tune.bufsize <= 0) {
842 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
843 err_code |= ERR_ALERT | ERR_FATAL;
844 goto out;
845 }
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100846 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100847 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200848 }
849 else if (!strcmp(args[0], "tune.maxrewrite")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200850 if (alertif_too_many_args(1, file, linenum, args, &err_code))
851 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200852 if (*(args[1]) == 0) {
853 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
854 err_code |= ERR_ALERT | ERR_FATAL;
855 goto out;
856 }
857 global.tune.maxrewrite = atol(args[1]);
Willy Tarreau27097842015-09-28 13:53:23 +0200858 if (global.tune.maxrewrite < 0) {
859 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
860 err_code |= ERR_ALERT | ERR_FATAL;
861 goto out;
862 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200863 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100864 else if (!strcmp(args[0], "tune.idletimer")) {
865 unsigned int idle;
866 const char *res;
867
William Lallemand1a748ae2015-05-19 16:37:23 +0200868 if (alertif_too_many_args(1, file, linenum, args, &err_code))
869 goto out;
Willy Tarreau7e312732014-02-12 16:35:14 +0100870 if (*(args[1]) == 0) {
871 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
872 err_code |= ERR_ALERT | ERR_FATAL;
873 goto out;
874 }
875
876 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
877 if (res) {
878 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
879 file, linenum, *res, args[0]);
880 err_code |= ERR_ALERT | ERR_FATAL;
881 goto out;
882 }
883
884 if (idle > 65535) {
885 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
886 err_code |= ERR_ALERT | ERR_FATAL;
887 goto out;
888 }
889 global.tune.idle_timer = idle;
890 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100891 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200892 if (alertif_too_many_args(1, file, linenum, args, &err_code))
893 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100894 if (global.tune.client_rcvbuf != 0) {
895 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
896 err_code |= ERR_ALERT;
897 goto out;
898 }
899 if (*(args[1]) == 0) {
900 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
901 err_code |= ERR_ALERT | ERR_FATAL;
902 goto out;
903 }
904 global.tune.client_rcvbuf = atol(args[1]);
905 }
906 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200907 if (alertif_too_many_args(1, file, linenum, args, &err_code))
908 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100909 if (global.tune.server_rcvbuf != 0) {
910 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
911 err_code |= ERR_ALERT;
912 goto out;
913 }
914 if (*(args[1]) == 0) {
915 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
916 err_code |= ERR_ALERT | ERR_FATAL;
917 goto out;
918 }
919 global.tune.server_rcvbuf = atol(args[1]);
920 }
921 else if (!strcmp(args[0], "tune.sndbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200922 if (alertif_too_many_args(1, file, linenum, args, &err_code))
923 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100924 if (global.tune.client_sndbuf != 0) {
925 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
926 err_code |= ERR_ALERT;
927 goto out;
928 }
929 if (*(args[1]) == 0) {
930 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
931 err_code |= ERR_ALERT | ERR_FATAL;
932 goto out;
933 }
934 global.tune.client_sndbuf = atol(args[1]);
935 }
936 else if (!strcmp(args[0], "tune.sndbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200937 if (alertif_too_many_args(1, file, linenum, args, &err_code))
938 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100939 if (global.tune.server_sndbuf != 0) {
940 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
941 err_code |= ERR_ALERT;
942 goto out;
943 }
944 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.server_sndbuf = atol(args[1]);
950 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200951 else if (!strcmp(args[0], "tune.pipesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200952 if (alertif_too_many_args(1, file, linenum, args, &err_code))
953 goto out;
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200954 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.pipesize = atol(args[1]);
960 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100961 else if (!strcmp(args[0], "tune.http.cookielen")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200962 if (alertif_too_many_args(1, file, linenum, args, &err_code))
963 goto out;
Willy Tarreau193b8c62012-11-22 00:17:38 +0100964 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.cookie_len = atol(args[1]) + 1;
970 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200971 else if (!strcmp(args[0], "tune.http.maxhdr")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200972 if (alertif_too_many_args(1, file, linenum, args, &err_code))
973 goto out;
Willy Tarreauac1932d2011-10-24 19:14:41 +0200974 if (*(args[1]) == 0) {
975 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
976 err_code |= ERR_ALERT | ERR_FATAL;
977 goto out;
978 }
979 global.tune.max_http_hdr = atol(args[1]);
980 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100981 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
982#ifdef USE_ZLIB
William Lallemand1a748ae2015-05-19 16:37:23 +0200983 if (alertif_too_many_args(1, file, linenum, args, &err_code))
984 goto out;
William Lallemanda509e4c2012-11-07 16:54:34 +0100985 if (*args[1]) {
986 global.tune.zlibmemlevel = atoi(args[1]);
987 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
988 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
989 file, linenum, args[0]);
990 err_code |= ERR_ALERT | ERR_FATAL;
991 goto out;
992 }
993 } else {
994 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
995 file, linenum, args[0]);
996 err_code |= ERR_ALERT | ERR_FATAL;
997 goto out;
998 }
999#else
1000 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1001 err_code |= ERR_ALERT | ERR_FATAL;
1002 goto out;
1003#endif
1004 }
1005 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
1006#ifdef USE_ZLIB
William Lallemand1a748ae2015-05-19 16:37:23 +02001007 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1008 goto out;
William Lallemanda509e4c2012-11-07 16:54:34 +01001009 if (*args[1]) {
1010 global.tune.zlibwindowsize = atoi(args[1]);
1011 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
1012 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
1013 file, linenum, args[0]);
1014 err_code |= ERR_ALERT | ERR_FATAL;
1015 goto out;
1016 }
1017 } else {
1018 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
1019 file, linenum, args[0]);
1020 err_code |= ERR_ALERT | ERR_FATAL;
1021 goto out;
1022 }
1023#else
1024 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1025 err_code |= ERR_ALERT | ERR_FATAL;
1026 goto out;
1027#endif
1028 }
William Lallemandf3747832012-11-09 12:33:10 +01001029 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001030 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1031 goto out;
William Lallemandf3747832012-11-09 12:33:10 +01001032 if (*args[1]) {
1033 global.tune.comp_maxlevel = atoi(args[1]);
1034 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
1035 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1036 file, linenum, args[0]);
1037 err_code |= ERR_ALERT | ERR_FATAL;
1038 goto out;
1039 }
1040 } else {
1041 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1042 file, linenum, args[0]);
1043 err_code |= ERR_ALERT | ERR_FATAL;
1044 goto out;
1045 }
1046 }
Willy Tarreauf3045d22015-04-29 16:24:50 +02001047 else if (!strcmp(args[0], "tune.pattern.cache-size")) {
1048 if (*args[1]) {
1049 global.tune.pattern_cache = atoi(args[1]);
1050 if (global.tune.pattern_cache < 0) {
1051 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
1052 file, linenum, args[0]);
1053 err_code |= ERR_ALERT | ERR_FATAL;
1054 goto out;
1055 }
1056 } else {
1057 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
1058 file, linenum, args[0]);
1059 err_code |= ERR_ALERT | ERR_FATAL;
1060 goto out;
1061 }
1062 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001063 else if (!strcmp(args[0], "uid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001064 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1065 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001066 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001067 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001068 err_code |= ERR_ALERT;
1069 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001070 }
1071 if (*(args[1]) == 0) {
1072 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001073 err_code |= ERR_ALERT | ERR_FATAL;
1074 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001075 }
1076 global.uid = atol(args[1]);
1077 }
1078 else if (!strcmp(args[0], "gid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001079 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1080 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001081 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001082 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001083 err_code |= ERR_ALERT;
1084 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001085 }
1086 if (*(args[1]) == 0) {
1087 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001088 err_code |= ERR_ALERT | ERR_FATAL;
1089 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001090 }
1091 global.gid = atol(args[1]);
1092 }
Simon Horman98637e52014-06-20 12:30:16 +09001093 else if (!strcmp(args[0], "external-check")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001094 if (alertif_too_many_args(0, file, linenum, args, &err_code))
1095 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09001096 global.external_check = 1;
1097 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001098 /* user/group name handling */
1099 else if (!strcmp(args[0], "user")) {
1100 struct passwd *ha_user;
William Lallemand1a748ae2015-05-19 16:37:23 +02001101 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1102 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001103 if (global.uid != 0) {
1104 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001105 err_code |= ERR_ALERT;
1106 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001107 }
1108 errno = 0;
1109 ha_user = getpwnam(args[1]);
1110 if (ha_user != NULL) {
1111 global.uid = (int)ha_user->pw_uid;
1112 }
1113 else {
1114 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 +02001115 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001116 }
1117 }
1118 else if (!strcmp(args[0], "group")) {
1119 struct group *ha_group;
William Lallemand1a748ae2015-05-19 16:37:23 +02001120 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1121 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001122 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02001123 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001124 err_code |= ERR_ALERT;
1125 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001126 }
1127 errno = 0;
1128 ha_group = getgrnam(args[1]);
1129 if (ha_group != NULL) {
1130 global.gid = (int)ha_group->gr_gid;
1131 }
1132 else {
1133 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 +02001134 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001135 }
1136 }
1137 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +02001138 else if (!strcmp(args[0], "nbproc")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001139 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1140 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001141 if (*(args[1]) == 0) {
1142 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001143 err_code |= ERR_ALERT | ERR_FATAL;
1144 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001145 }
1146 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001147 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
1148 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
1149 file, linenum, args[0], LONGBITS, global.nbproc);
1150 err_code |= ERR_ALERT | ERR_FATAL;
1151 goto out;
1152 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001153 }
1154 else if (!strcmp(args[0], "maxconn")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001155 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1156 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001157 if (global.maxconn != 0) {
1158 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001159 err_code |= ERR_ALERT;
1160 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001161 }
1162 if (*(args[1]) == 0) {
1163 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001164 err_code |= ERR_ALERT | ERR_FATAL;
1165 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001166 }
1167 global.maxconn = atol(args[1]);
1168#ifdef SYSTEM_MAXCONN
1169 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
1170 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);
1171 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +02001172 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001173 }
1174#endif /* SYSTEM_MAXCONN */
1175 }
Willy Tarreau403edff2012-09-06 11:58:37 +02001176 else if (!strcmp(args[0], "maxsslconn")) {
1177#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001178 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1179 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001180 if (*(args[1]) == 0) {
1181 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1182 err_code |= ERR_ALERT | ERR_FATAL;
1183 goto out;
1184 }
1185 global.maxsslconn = atol(args[1]);
1186#else
Emeric Brun0914df82012-10-02 18:45:42 +02001187 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1188 err_code |= ERR_ALERT | ERR_FATAL;
1189 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001190#endif
1191 }
Willy Tarreau610f04b2014-02-13 11:36:41 +01001192 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
1193#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001194 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1195 goto out;
Willy Tarreau610f04b2014-02-13 11:36:41 +01001196 if (*(args[1]) == 0) {
1197 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1198 err_code |= ERR_ALERT | ERR_FATAL;
1199 goto out;
1200 }
1201 free(global.listen_default_ciphers);
1202 global.listen_default_ciphers = strdup(args[1]);
1203#else
1204 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1205 err_code |= ERR_ALERT | ERR_FATAL;
1206 goto out;
1207#endif
1208 }
1209 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
1210#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001211 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1212 goto out;
Willy Tarreau610f04b2014-02-13 11:36:41 +01001213 if (*(args[1]) == 0) {
1214 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1215 err_code |= ERR_ALERT | ERR_FATAL;
1216 goto out;
1217 }
1218 free(global.connect_default_ciphers);
1219 global.connect_default_ciphers = strdup(args[1]);
1220#else
1221 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1222 err_code |= ERR_ALERT | ERR_FATAL;
1223 goto out;
1224#endif
1225 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02001226#ifdef USE_OPENSSL
1227#ifndef OPENSSL_NO_DH
1228 else if (!strcmp(args[0], "ssl-dh-param-file")) {
1229 if (*(args[1]) == 0) {
1230 Alert("parsing [%s:%d] : '%s' expects a file path as an argument.\n", file, linenum, args[0]);
1231 err_code |= ERR_ALERT | ERR_FATAL;
1232 goto out;
1233 }
1234 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
1235 Alert("parsing [%s:%d] : '%s': unable to load DH parameters from file <%s>.\n", file, linenum, args[0], args[1]);
1236 err_code |= ERR_ALERT | ERR_FATAL;
1237 goto out;
1238 }
1239 }
1240#endif
1241#endif
Emeric Brun850efd52014-01-29 12:24:34 +01001242 else if (!strcmp(args[0], "ssl-server-verify")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001243 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1244 goto out;
Emeric Brun850efd52014-01-29 12:24:34 +01001245 if (*(args[1]) == 0) {
1246 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1247 err_code |= ERR_ALERT | ERR_FATAL;
1248 goto out;
1249 }
1250 if (strcmp(args[1],"none") == 0)
1251 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1252 else if (strcmp(args[1],"required") == 0)
1253 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1254 else {
1255 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1256 err_code |= ERR_ALERT | ERR_FATAL;
1257 goto out;
1258 }
1259 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001260 else if (!strcmp(args[0], "maxconnrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001261 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1262 goto out;
Willy Tarreau81c25d02011-09-07 15:17:21 +02001263 if (global.cps_lim != 0) {
1264 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1265 err_code |= ERR_ALERT;
1266 goto out;
1267 }
1268 if (*(args[1]) == 0) {
1269 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1270 err_code |= ERR_ALERT | ERR_FATAL;
1271 goto out;
1272 }
1273 global.cps_lim = atol(args[1]);
1274 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001275 else if (!strcmp(args[0], "maxsessrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001276 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1277 goto out;
Willy Tarreau93e7c002013-10-07 18:51:07 +02001278 if (global.sps_lim != 0) {
1279 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1280 err_code |= ERR_ALERT;
1281 goto out;
1282 }
1283 if (*(args[1]) == 0) {
1284 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1285 err_code |= ERR_ALERT | ERR_FATAL;
1286 goto out;
1287 }
1288 global.sps_lim = atol(args[1]);
1289 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001290 else if (!strcmp(args[0], "maxsslrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001291 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1292 goto out;
Willy Tarreaue43d5322013-10-07 20:01:52 +02001293 if (global.ssl_lim != 0) {
1294 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1295 err_code |= ERR_ALERT;
1296 goto out;
1297 }
1298 if (*(args[1]) == 0) {
1299 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1300 err_code |= ERR_ALERT | ERR_FATAL;
1301 goto out;
1302 }
1303 global.ssl_lim = atol(args[1]);
1304 }
William Lallemandd85f9172012-11-09 17:05:39 +01001305 else if (!strcmp(args[0], "maxcomprate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001306 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1307 goto out;
William Lallemandd85f9172012-11-09 17:05:39 +01001308 if (*(args[1]) == 0) {
1309 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1310 err_code |= ERR_ALERT | ERR_FATAL;
1311 goto out;
1312 }
1313 global.comp_rate_lim = atoi(args[1]) * 1024;
1314 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001315 else if (!strcmp(args[0], "maxpipes")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001316 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1317 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001318 if (global.maxpipes != 0) {
1319 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001320 err_code |= ERR_ALERT;
1321 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001322 }
1323 if (*(args[1]) == 0) {
1324 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001325 err_code |= ERR_ALERT | ERR_FATAL;
1326 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001327 }
1328 global.maxpipes = atol(args[1]);
1329 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001330 else if (!strcmp(args[0], "maxzlibmem")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001331 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1332 goto out;
William Lallemand9d5f5482012-11-07 16:12:57 +01001333 if (*(args[1]) == 0) {
1334 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1335 err_code |= ERR_ALERT | ERR_FATAL;
1336 goto out;
1337 }
William Lallemande3a7d992012-11-20 11:25:20 +01001338 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001339 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001340 else if (!strcmp(args[0], "maxcompcpuusage")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001341 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1342 goto out;
William Lallemand072a2bf2012-11-20 17:01:01 +01001343 if (*(args[1]) == 0) {
1344 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1345 err_code |= ERR_ALERT | ERR_FATAL;
1346 goto out;
1347 }
1348 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001349 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001350 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1351 err_code |= ERR_ALERT | ERR_FATAL;
1352 goto out;
1353 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001354 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001355
Willy Tarreaubaaee002006-06-26 02:48:02 +02001356 else if (!strcmp(args[0], "ulimit-n")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001357 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1358 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001359 if (global.rlimit_nofile != 0) {
1360 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001361 err_code |= ERR_ALERT;
1362 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001363 }
1364 if (*(args[1]) == 0) {
1365 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001366 err_code |= ERR_ALERT | ERR_FATAL;
1367 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001368 }
1369 global.rlimit_nofile = atol(args[1]);
1370 }
1371 else if (!strcmp(args[0], "chroot")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001372 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1373 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001374 if (global.chroot != NULL) {
1375 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001376 err_code |= ERR_ALERT;
1377 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001378 }
1379 if (*(args[1]) == 0) {
1380 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001381 err_code |= ERR_ALERT | ERR_FATAL;
1382 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001383 }
1384 global.chroot = strdup(args[1]);
1385 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001386 else if (!strcmp(args[0], "description")) {
1387 int i, len=0;
1388 char *d;
1389
1390 if (!*args[1]) {
1391 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1392 file, linenum, args[0]);
1393 err_code |= ERR_ALERT | ERR_FATAL;
1394 goto out;
1395 }
1396
Willy Tarreau348acfe2014-04-14 15:00:39 +02001397 for (i = 1; *args[i]; i++)
1398 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001399
1400 if (global.desc)
1401 free(global.desc);
1402
1403 global.desc = d = (char *)calloc(1, len);
1404
Willy Tarreau348acfe2014-04-14 15:00:39 +02001405 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1406 for (i = 2; *args[i]; i++)
1407 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001408 }
1409 else if (!strcmp(args[0], "node")) {
1410 int i;
1411 char c;
1412
William Lallemand1a748ae2015-05-19 16:37:23 +02001413 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1414 goto out;
1415
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001416 for (i=0; args[1][i]; i++) {
1417 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001418 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1419 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001420 break;
1421 }
1422
1423 if (!i || args[1][i]) {
1424 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1425 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1426 file, linenum, args[0]);
1427 err_code |= ERR_ALERT | ERR_FATAL;
1428 goto out;
1429 }
1430
1431 if (global.node)
1432 free(global.node);
1433
1434 global.node = strdup(args[1]);
1435 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001436 else if (!strcmp(args[0], "pidfile")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001437 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1438 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001439 if (global.pidfile != NULL) {
1440 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001441 err_code |= ERR_ALERT;
1442 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001443 }
1444 if (*(args[1]) == 0) {
1445 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001446 err_code |= ERR_ALERT | ERR_FATAL;
1447 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001448 }
1449 global.pidfile = strdup(args[1]);
1450 }
Emeric Bruned760922010-10-22 17:59:25 +02001451 else if (!strcmp(args[0], "unix-bind")) {
1452 int cur_arg = 1;
1453 while (*(args[cur_arg])) {
1454 if (!strcmp(args[cur_arg], "prefix")) {
1455 if (global.unix_bind.prefix != NULL) {
1456 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1457 err_code |= ERR_ALERT;
1458 cur_arg += 2;
1459 continue;
1460 }
1461
1462 if (*(args[cur_arg+1]) == 0) {
1463 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1464 err_code |= ERR_ALERT | ERR_FATAL;
1465 goto out;
1466 }
1467 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1468 cur_arg += 2;
1469 continue;
1470 }
1471
1472 if (!strcmp(args[cur_arg], "mode")) {
1473
1474 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1475 cur_arg += 2;
1476 continue;
1477 }
1478
1479 if (!strcmp(args[cur_arg], "uid")) {
1480
1481 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1482 cur_arg += 2;
1483 continue;
1484 }
1485
1486 if (!strcmp(args[cur_arg], "gid")) {
1487
1488 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1489 cur_arg += 2;
1490 continue;
1491 }
1492
1493 if (!strcmp(args[cur_arg], "user")) {
1494 struct passwd *user;
1495
1496 user = getpwnam(args[cur_arg + 1]);
1497 if (!user) {
1498 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1499 file, linenum, args[0], args[cur_arg + 1 ]);
1500 err_code |= ERR_ALERT | ERR_FATAL;
1501 goto out;
1502 }
1503
1504 global.unix_bind.ux.uid = user->pw_uid;
1505 cur_arg += 2;
1506 continue;
1507 }
1508
1509 if (!strcmp(args[cur_arg], "group")) {
1510 struct group *group;
1511
1512 group = getgrnam(args[cur_arg + 1]);
1513 if (!group) {
1514 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1515 file, linenum, args[0], args[cur_arg + 1 ]);
1516 err_code |= ERR_ALERT | ERR_FATAL;
1517 goto out;
1518 }
1519
1520 global.unix_bind.ux.gid = group->gr_gid;
1521 cur_arg += 2;
1522 continue;
1523 }
1524
Willy Tarreaub48f9582011-09-05 01:17:06 +02001525 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001526 file, linenum, args[0]);
1527 err_code |= ERR_ALERT | ERR_FATAL;
1528 goto out;
1529 }
1530 }
William Lallemand0f99e342011-10-12 17:50:54 +02001531 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1532 /* delete previous herited or defined syslog servers */
1533 struct logsrv *back;
1534 struct logsrv *tmp;
1535
1536 if (*(args[1]) != 0) {
1537 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1538 err_code |= ERR_ALERT | ERR_FATAL;
1539 goto out;
1540 }
1541
1542 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1543 LIST_DEL(&tmp->list);
1544 free(tmp);
1545 }
1546 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001547 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001548 struct sockaddr_storage *sk;
1549 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001550 struct logsrv *logsrv;
Willy Tarreau18324f52014-06-27 18:10:07 +02001551 int arg = 0;
1552 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001553
William Lallemand1a748ae2015-05-19 16:37:23 +02001554 if (alertif_too_many_args(8, file, linenum, args, &err_code)) /* does not strictly check optional arguments */
1555 goto out;
1556
Willy Tarreaubaaee002006-06-26 02:48:02 +02001557 if (*(args[1]) == 0 || *(args[2]) == 0) {
1558 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001559 err_code |= ERR_ALERT | ERR_FATAL;
1560 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001561 }
William Lallemand0f99e342011-10-12 17:50:54 +02001562
1563 logsrv = calloc(1, sizeof(struct logsrv));
1564
Willy Tarreau18324f52014-06-27 18:10:07 +02001565 /* just after the address, a length may be specified */
1566 if (strcmp(args[arg+2], "len") == 0) {
1567 len = atoi(args[arg+3]);
1568 if (len < 80 || len > 65535) {
1569 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1570 file, linenum, args[arg+3]);
1571 err_code |= ERR_ALERT | ERR_FATAL;
1572 goto out;
1573 }
1574 logsrv->maxlen = len;
1575
1576 /* skip these two args */
1577 arg += 2;
1578 }
1579 else
1580 logsrv->maxlen = MAX_SYSLOG_LEN;
1581
1582 if (logsrv->maxlen > global.max_syslog_len) {
1583 global.max_syslog_len = logsrv->maxlen;
Dragan Dosen59cee972015-09-19 22:09:02 +02001584 logheader = realloc(logheader, global.max_syslog_len + 1);
Dragan Dosen1322d092015-09-22 16:05:32 +02001585 logheader_rfc5424 = realloc(logheader_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02001586 logline = realloc(logline, global.max_syslog_len + 1);
Dragan Dosen0b85ece2015-09-25 19:17:44 +02001587 logline_rfc5424 = realloc(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02001588 }
1589
Dragan Dosen1322d092015-09-22 16:05:32 +02001590 /* after the length, a format may be specified */
1591 if (strcmp(args[arg+2], "format") == 0) {
1592 logsrv->format = get_log_format(args[arg+3]);
1593 if (logsrv->format < 0) {
1594 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
1595 err_code |= ERR_ALERT | ERR_FATAL;
1596 goto out;
1597 }
1598
1599 /* skip these two args */
1600 arg += 2;
1601 }
1602
William Lallemand1a748ae2015-05-19 16:37:23 +02001603 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
1604 goto out;
1605
Willy Tarreau18324f52014-06-27 18:10:07 +02001606 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001607 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001608 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001609 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001610 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001611 }
1612
William Lallemand0f99e342011-10-12 17:50:54 +02001613 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02001614 if (*(args[arg+3])) {
1615 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001616 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001617 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001618 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001619 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001620 }
1621 }
1622
William Lallemand0f99e342011-10-12 17:50:54 +02001623 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02001624 if (*(args[arg+4])) {
1625 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001626 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001627 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001628 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001629 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001630 }
1631 }
1632
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02001633 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001634 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001635 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001636 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001637 free(logsrv);
1638 goto out;
1639 }
1640 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001641
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001642 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001643 if (port1 != port2) {
1644 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1645 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001646 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001647 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001648 goto out;
1649 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001650
William Lallemand0f99e342011-10-12 17:50:54 +02001651 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001652 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001653 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001654 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001655
William Lallemand0f99e342011-10-12 17:50:54 +02001656 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001657 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001658 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1659 char *name;
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001660
1661 if (global.log_send_hostname != NULL) {
1662 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1663 err_code |= ERR_ALERT;
1664 goto out;
1665 }
1666
1667 if (*(args[1]))
1668 name = args[1];
1669 else
1670 name = hostname;
1671
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001672 free(global.log_send_hostname);
Dragan Dosenc8cfa7b2015-09-28 13:28:21 +02001673 global.log_send_hostname = strdup(name);
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001674 }
Baptiste Assmann6bc89362015-08-23 09:22:25 +02001675 else if (!strcmp(args[0], "server-state-base")) { /* path base where HAProxy can find server state files */
1676 if (global.server_state_base != NULL) {
1677 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1678 err_code |= ERR_ALERT;
1679 goto out;
1680 }
1681
1682 if (!*(args[1])) {
1683 Alert("parsing [%s:%d] : '%s' expects one argument: a directory path.\n", file, linenum, args[0]);
1684 err_code |= ERR_FATAL;
1685 goto out;
1686 }
1687
1688 global.server_state_base = strdup(args[1]);
1689 }
Baptiste Assmanne0882262015-08-23 09:54:31 +02001690 else if (!strcmp(args[0], "server-state-file")) { /* path to the file where HAProxy can load the server states */
1691 if (global.server_state_file != NULL) {
1692 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1693 err_code |= ERR_ALERT;
1694 goto out;
1695 }
1696
1697 if (!*(args[1])) {
1698 Alert("parsing [%s:%d] : '%s' expect one argument: a file path.\n", file, linenum, args[0]);
1699 err_code |= ERR_FATAL;
1700 goto out;
1701 }
1702
1703 global.server_state_file = strdup(args[1]);
1704 }
Kevinm48936af2010-12-22 16:08:21 +00001705 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
William Lallemand1a748ae2015-05-19 16:37:23 +02001706 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1707 goto out;
Kevinm48936af2010-12-22 16:08:21 +00001708 if (*(args[1]) == 0) {
1709 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1710 err_code |= ERR_ALERT | ERR_FATAL;
1711 goto out;
1712 }
Dragan Dosen43885c72015-10-01 13:18:13 +02001713 chunk_destroy(&global.log_tag);
1714 chunk_initstr(&global.log_tag, strdup(args[1]));
Kevinm48936af2010-12-22 16:08:21 +00001715 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001716 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
William Lallemand1a748ae2015-05-19 16:37:23 +02001717 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1718 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001719 if (global.spread_checks != 0) {
1720 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001721 err_code |= ERR_ALERT;
1722 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001723 }
1724 if (*(args[1]) == 0) {
1725 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001726 err_code |= ERR_ALERT | ERR_FATAL;
1727 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001728 }
1729 global.spread_checks = atol(args[1]);
1730 if (global.spread_checks < 0 || global.spread_checks > 50) {
1731 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001732 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001733 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001734 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001735 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1736 const char *err;
1737 unsigned int val;
1738
William Lallemand1a748ae2015-05-19 16:37:23 +02001739 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1740 goto out;
Willy Tarreau1746eec2014-04-25 10:46:47 +02001741 if (*(args[1]) == 0) {
1742 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1743 err_code |= ERR_ALERT | ERR_FATAL;
1744 goto out;
1745 }
1746
1747 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1748 if (err) {
1749 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1750 err_code |= ERR_ALERT | ERR_FATAL;
1751 }
1752 global.max_spread_checks = val;
1753 if (global.max_spread_checks < 0) {
1754 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1755 err_code |= ERR_ALERT | ERR_FATAL;
1756 }
1757 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001758 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1759#ifdef USE_CPU_AFFINITY
1760 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001761 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001762 unsigned long cpus = 0;
1763
1764 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001765 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001766 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001767 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001768 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001769 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001770 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001771 proc = atol(args[1]);
1772 if (proc >= 1 && proc <= LONGBITS)
1773 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001774 }
1775
1776 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001777 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",
1778 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001779 err_code |= ERR_ALERT | ERR_FATAL;
1780 goto out;
1781 }
1782
1783 cur_arg = 2;
1784 while (*args[cur_arg]) {
1785 unsigned int low, high;
1786
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001787 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001788 char *dash = strchr(args[cur_arg], '-');
1789
1790 low = high = str2uic(args[cur_arg]);
1791 if (dash)
1792 high = str2uic(dash + 1);
1793
1794 if (high < low) {
1795 unsigned int swap = low;
1796 low = high;
1797 high = swap;
1798 }
1799
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001800 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001801 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001802 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001803 err_code |= ERR_ALERT | ERR_FATAL;
1804 goto out;
1805 }
1806
1807 while (low <= high)
1808 cpus |= 1UL << low++;
1809 }
1810 else {
1811 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1812 file, linenum, args[0], args[cur_arg]);
1813 err_code |= ERR_ALERT | ERR_FATAL;
1814 goto out;
1815 }
1816 cur_arg++;
1817 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001818 for (i = 0; i < LONGBITS; i++)
1819 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001820 global.cpu_map[i] = cpus;
1821#else
1822 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1823 err_code |= ERR_ALERT | ERR_FATAL;
1824 goto out;
1825#endif
1826 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001827 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001828 struct cfg_kw_list *kwl;
1829 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001830 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001831
1832 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1833 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1834 if (kwl->kw[index].section != CFG_GLOBAL)
1835 continue;
1836 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001837 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001838 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001839 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001840 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001841 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001842 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001843 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001844 err_code |= ERR_WARN;
1845 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001846 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001847 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001848 }
1849 }
1850 }
1851
Willy Tarreaubaaee002006-06-26 02:48:02 +02001852 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001853 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001854 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001855
Willy Tarreau058e9072009-07-20 09:30:05 +02001856 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001857 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001858 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001859}
1860
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001861void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001862{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001863 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001864 defproxy.mode = PR_MODE_TCP;
1865 defproxy.state = PR_STNEW;
1866 defproxy.maxconn = cfg_maxpconn;
1867 defproxy.conn_retries = CONN_RETRIES;
Joseph Lynch726ab712015-05-11 23:25:34 -07001868 defproxy.redispatch_after = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001869
Simon Horman66183002013-02-23 10:16:43 +09001870 defproxy.defsrv.check.inter = DEF_CHKINTR;
1871 defproxy.defsrv.check.fastinter = 0;
1872 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001873 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1874 defproxy.defsrv.agent.fastinter = 0;
1875 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001876 defproxy.defsrv.check.rise = DEF_RISETIME;
1877 defproxy.defsrv.check.fall = DEF_FALLTIME;
1878 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1879 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001880 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001881 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001882 defproxy.defsrv.maxqueue = 0;
1883 defproxy.defsrv.minconn = 0;
1884 defproxy.defsrv.maxconn = 0;
1885 defproxy.defsrv.slowstart = 0;
1886 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1887 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1888 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Simon Horman64e34162015-02-06 11:11:57 +09001889
1890 defproxy.email_alert.level = LOG_ALERT;
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02001891 defproxy.load_server_state_from_file = PR_SRV_STATE_FILE_UNSPEC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001892}
1893
Willy Tarreauade5ec42010-01-28 19:33:49 +01001894
Willy Tarreau63af98d2014-05-18 08:11:41 +02001895/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1896 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1897 * ERR_FATAL in case of error.
1898 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001899static int create_cond_regex_rule(const char *file, int line,
1900 struct proxy *px, int dir, int action, int flags,
1901 const char *cmd, const char *reg, const char *repl,
1902 const char **cond_start)
1903{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001904 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001905 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001906 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001907 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001908 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001909 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001910 int cs;
1911 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001912
1913 if (px == &defproxy) {
1914 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001915 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001916 goto err;
1917 }
1918
1919 if (*reg == 0) {
1920 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001921 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001922 goto err;
1923 }
1924
1925 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001926 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001927
Willy Tarreau5321c422010-01-28 20:35:13 +01001928 if (cond_start &&
1929 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001930 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1931 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1932 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001933 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001934 goto err;
1935 }
1936 }
1937 else if (cond_start && **cond_start) {
1938 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1939 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001940 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001941 goto err;
1942 }
1943
Willy Tarreau63af98d2014-05-18 08:11:41 +02001944 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001945 (dir == SMP_OPT_DIR_REQ) ?
1946 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1947 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1948 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001949
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001950 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001951 if (!preg) {
1952 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
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
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001957 cs = !(flags & REG_ICASE);
1958 cap = !(flags & REG_NOSUB);
1959 error = NULL;
1960 if (!regex_comp(reg, preg, cs, cap, &error)) {
1961 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1962 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001963 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001964 goto err;
1965 }
1966
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001967 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001968 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001969 if (repl && err) {
1970 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1971 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001972 ret_code |= ERR_ALERT | ERR_FATAL;
1973 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001974 }
1975
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001976 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001977 ret_code |= ERR_WARN;
1978
1979 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001980
Willy Tarreau63af98d2014-05-18 08:11:41 +02001981 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001982 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001983 err:
1984 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001985 free(errmsg);
1986 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001987}
1988
Willy Tarreaubaaee002006-06-26 02:48:02 +02001989/*
William Lallemand51097192015-04-14 16:35:22 +02001990 * Parse a line in a <listen>, <frontend> or <backend> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001991 * Returns the error code, 0 if OK, or any combination of :
1992 * - ERR_ABORT: must abort ASAP
1993 * - ERR_FATAL: we can continue parsing but not start the service
1994 * - ERR_WARN: a warning has been emitted
1995 * - ERR_ALERT: an alert has been emitted
1996 * Only the two first ones can stop processing, the two others are just
1997 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001998 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001999int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
2000{
2001 static struct peers *curpeers = NULL;
2002 struct peer *newpeer = NULL;
2003 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002004 struct bind_conf *bind_conf;
2005 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02002006 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01002007 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02002008
2009 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002010 if (!*args[1]) {
2011 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01002012 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002013 goto out;
2014 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002015
William Lallemand6e62fb62015-04-28 16:55:23 +02002016 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2017 goto out;
2018
Emeric Brun32da3c42010-09-23 18:39:19 +02002019 err = invalid_char(args[1]);
2020 if (err) {
2021 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2022 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01002023 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002024 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002025 }
2026
2027 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
2028 /*
2029 * If there are two proxies with the same name only following
2030 * combinations are allowed:
2031 */
2032 if (strcmp(curpeers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002033 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 +02002034 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002035 err_code |= ERR_ALERT | ERR_FATAL;
Emeric Brun32da3c42010-09-23 18:39:19 +02002036 }
2037 }
2038
2039 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
2040 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2041 err_code |= ERR_ALERT | ERR_ABORT;
2042 goto out;
2043 }
2044
2045 curpeers->next = peers;
2046 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002047 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002048 curpeers->conf.line = linenum;
2049 curpeers->last_change = now.tv_sec;
2050 curpeers->id = strdup(args[1]);
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002051 curpeers->state = PR_STNEW;
Emeric Brun32da3c42010-09-23 18:39:19 +02002052 }
2053 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01002054 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01002055 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002056 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02002057
2058 if (!*args[2]) {
2059 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2060 file, linenum, args[0]);
2061 err_code |= ERR_ALERT | ERR_FATAL;
2062 goto out;
2063 }
2064
2065 err = invalid_char(args[1]);
2066 if (err) {
2067 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2068 file, linenum, *err, args[1]);
2069 err_code |= ERR_ALERT | ERR_FATAL;
2070 goto out;
2071 }
2072
2073 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
2074 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2075 err_code |= ERR_ALERT | ERR_ABORT;
2076 goto out;
2077 }
2078
2079 /* the peers are linked backwards first */
2080 curpeers->count++;
2081 newpeer->next = curpeers->remote;
2082 curpeers->remote = newpeer;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002083 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002084 newpeer->conf.line = linenum;
2085
2086 newpeer->last_change = now.tv_sec;
2087 newpeer->id = strdup(args[1]);
2088
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002089 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002090 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01002091 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002092 err_code |= ERR_ALERT | ERR_FATAL;
2093 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002094 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01002095
2096 proto = protocol_by_family(sk->ss_family);
2097 if (!proto || !proto->connect) {
2098 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2099 file, linenum, args[0], args[1]);
2100 err_code |= ERR_ALERT | ERR_FATAL;
2101 goto out;
2102 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002103
2104 if (port1 != port2) {
2105 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2106 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002107 err_code |= ERR_ALERT | ERR_FATAL;
2108 goto out;
2109 }
2110
Willy Tarreau2aa38802013-02-20 19:20:59 +01002111 if (!port1) {
2112 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2113 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002114 err_code |= ERR_ALERT | ERR_FATAL;
2115 goto out;
2116 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002117
Emeric Brun32da3c42010-09-23 18:39:19 +02002118 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002119 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002120 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02002121 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02002122
Emeric Brun32da3c42010-09-23 18:39:19 +02002123 if (strcmp(newpeer->id, localpeer) == 0) {
2124 /* Current is local peer, it define a frontend */
2125 newpeer->local = 1;
Emeric Brunb3971ab2015-05-12 18:49:09 +02002126 peers->local = newpeer;
Emeric Brun32da3c42010-09-23 18:39:19 +02002127
2128 if (!curpeers->peers_fe) {
2129 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
2130 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2131 err_code |= ERR_ALERT | ERR_ABORT;
2132 goto out;
2133 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002134
Willy Tarreau237250c2011-07-29 01:49:03 +02002135 init_new_proxy(curpeers->peers_fe);
2136 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02002137 curpeers->peers_fe->id = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002138 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
2139 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau91d96282015-03-13 15:47:26 +01002140 peers_setup_frontend(curpeers->peers_fe);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002141
2142 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
2143
Willy Tarreau902636f2013-03-10 19:44:48 +01002144 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
2145 if (errmsg && *errmsg) {
2146 indent_msg(&errmsg, 2);
2147 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002148 }
2149 else
2150 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
2151 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002152 err_code |= ERR_FATAL;
2153 goto out;
2154 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02002155
2156 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01002157 l->maxaccept = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002158 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
2159 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
Willy Tarreau9903f0e2015-04-04 18:50:31 +02002160 l->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02002161 l->handler = process_stream;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002162 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01002163 l->default_target = ((struct proxy *)curpeers->peers_fe)->default_target;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002164 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
2165 global.maxsock += l->maxconn;
2166 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002167 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01002168 else {
2169 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
2170 file, linenum, args[0], args[1],
2171 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
2172 err_code |= ERR_FATAL;
2173 goto out;
2174 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002175 }
2176 } /* neither "peer" nor "peers" */
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002177 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
2178 curpeers->state = PR_STSTOPPED;
2179 }
2180 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
2181 curpeers->state = PR_STNEW;
2182 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002183 else if (*args[0] != 0) {
2184 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2185 err_code |= ERR_ALERT | ERR_FATAL;
2186 goto out;
2187 }
2188
2189out:
Willy Tarreau902636f2013-03-10 19:44:48 +01002190 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02002191 return err_code;
2192}
2193
Baptiste Assmann325137d2015-04-13 23:40:55 +02002194/*
2195 * Parse a <resolvers> section.
2196 * Returns the error code, 0 if OK, or any combination of :
2197 * - ERR_ABORT: must abort ASAP
2198 * - ERR_FATAL: we can continue parsing but not start the service
2199 * - ERR_WARN: a warning has been emitted
2200 * - ERR_ALERT: an alert has been emitted
2201 * Only the two first ones can stop processing, the two others are just
2202 * indicators.
2203 */
2204int cfg_parse_resolvers(const char *file, int linenum, char **args, int kwm)
2205{
2206 static struct dns_resolvers *curr_resolvers = NULL;
2207 struct dns_nameserver *newnameserver = NULL;
2208 const char *err;
2209 int err_code = 0;
2210 char *errmsg = NULL;
2211
2212 if (strcmp(args[0], "resolvers") == 0) { /* new resolvers section */
2213 if (!*args[1]) {
2214 Alert("parsing [%s:%d] : missing name for resolvers section.\n", file, linenum);
2215 err_code |= ERR_ALERT | ERR_ABORT;
2216 goto out;
2217 }
2218
2219 err = invalid_char(args[1]);
2220 if (err) {
2221 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2222 file, linenum, *err, args[0], args[1]);
2223 err_code |= ERR_ALERT | ERR_ABORT;
2224 goto out;
2225 }
2226
2227 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
2228 /* Error if two resolvers owns the same name */
2229 if (strcmp(curr_resolvers->id, args[1]) == 0) {
2230 Alert("Parsing [%s:%d]: resolvers '%s' has same name as another resolvers (declared at %s:%d).\n",
2231 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2232 err_code |= ERR_ALERT | ERR_ABORT;
2233 }
2234 }
2235
2236 if ((curr_resolvers = (struct dns_resolvers *)calloc(1, sizeof(struct dns_resolvers))) == NULL) {
2237 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2238 err_code |= ERR_ALERT | ERR_ABORT;
2239 goto out;
2240 }
2241
2242 /* default values */
2243 LIST_ADDQ(&dns_resolvers, &curr_resolvers->list);
2244 curr_resolvers->conf.file = strdup(file);
2245 curr_resolvers->conf.line = linenum;
2246 curr_resolvers->id = strdup(args[1]);
2247 curr_resolvers->query_ids = EB_ROOT;
2248 /* default hold period for valid is 10s */
Baptiste Assmann4c5490a2015-07-14 21:42:49 +02002249 curr_resolvers->hold.valid = 10000;
2250 curr_resolvers->timeout.retry = 1000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002251 curr_resolvers->resolve_retries = 3;
2252 LIST_INIT(&curr_resolvers->nameserver_list);
2253 LIST_INIT(&curr_resolvers->curr_resolution);
2254 }
2255 else if (strcmp(args[0], "nameserver") == 0) { /* nameserver definition */
2256 struct sockaddr_storage *sk;
2257 int port1, port2;
2258 struct protocol *proto;
2259
2260 if (!*args[2]) {
2261 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2262 file, linenum, args[0]);
2263 err_code |= ERR_ALERT | ERR_FATAL;
2264 goto out;
2265 }
2266
2267 err = invalid_char(args[1]);
2268 if (err) {
2269 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2270 file, linenum, *err, args[1]);
2271 err_code |= ERR_ALERT | ERR_FATAL;
2272 goto out;
2273 }
2274
Baptiste Assmanna315c552015-11-02 22:55:49 +01002275 list_for_each_entry(newnameserver, &curr_resolvers->nameserver_list, list) {
2276 /* Error if two resolvers owns the same name */
2277 if (strcmp(newnameserver->id, args[1]) == 0) {
2278 Alert("Parsing [%s:%d]: nameserver '%s' has same name as another nameserver (declared at %s:%d).\n",
2279 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2280 err_code |= ERR_ALERT | ERR_FATAL;
2281 }
2282 }
2283
Baptiste Assmann325137d2015-04-13 23:40:55 +02002284 if ((newnameserver = (struct dns_nameserver *)calloc(1, sizeof(struct dns_nameserver))) == NULL) {
2285 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2286 err_code |= ERR_ALERT | ERR_ABORT;
2287 goto out;
2288 }
2289
2290 /* the nameservers are linked backward first */
2291 LIST_ADDQ(&curr_resolvers->nameserver_list, &newnameserver->list);
2292 curr_resolvers->count_nameservers++;
2293 newnameserver->resolvers = curr_resolvers;
2294 newnameserver->conf.file = strdup(file);
2295 newnameserver->conf.line = linenum;
2296 newnameserver->id = strdup(args[1]);
2297
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002298 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002299 if (!sk) {
2300 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2301 err_code |= ERR_ALERT | ERR_FATAL;
2302 goto out;
2303 }
2304
2305 proto = protocol_by_family(sk->ss_family);
2306 if (!proto || !proto->connect) {
2307 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2308 file, linenum, args[0], args[1]);
2309 err_code |= ERR_ALERT | ERR_FATAL;
2310 goto out;
2311 }
2312
2313 if (port1 != port2) {
2314 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2315 file, linenum, args[0], args[1], args[2]);
2316 err_code |= ERR_ALERT | ERR_FATAL;
2317 goto out;
2318 }
2319
2320 newnameserver->addr = *sk;
2321 }
2322 else if (strcmp(args[0], "hold") == 0) { /* hold periods */
2323 const char *res;
2324 unsigned int time;
2325
2326 if (!*args[2]) {
2327 Alert("parsing [%s:%d] : '%s' expects an <event> and a <time> as arguments.\n",
2328 file, linenum, args[0]);
2329 Alert("<event> can be either 'valid', 'nx', 'refused', 'timeout', or 'other'\n");
2330 err_code |= ERR_ALERT | ERR_FATAL;
2331 goto out;
2332 }
2333 res = parse_time_err(args[2], &time, TIME_UNIT_MS);
2334 if (res) {
2335 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2336 file, linenum, *res, args[0]);
2337 err_code |= ERR_ALERT | ERR_FATAL;
2338 goto out;
2339 }
2340 if (strcmp(args[1], "valid") == 0)
2341 curr_resolvers->hold.valid = time;
2342 else {
2343 Alert("parsing [%s:%d] : '%s' unknown <event>: '%s', expects 'valid'\n",
2344 file, linenum, args[0], args[1]);
2345 err_code |= ERR_ALERT | ERR_FATAL;
2346 goto out;
2347 }
2348
2349 }
2350 else if (strcmp(args[0], "resolve_retries") == 0) {
2351 if (!*args[1]) {
2352 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2353 file, linenum, args[0]);
2354 err_code |= ERR_ALERT | ERR_FATAL;
2355 goto out;
2356 }
2357 curr_resolvers->resolve_retries = atoi(args[1]);
2358 }
2359 else if (strcmp(args[0], "timeout") == 0) {
2360 const char *res;
2361 unsigned int timeout_retry;
2362
2363 if (!*args[2]) {
2364 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments.\n",
2365 file, linenum, args[0]);
2366 err_code |= ERR_ALERT | ERR_FATAL;
2367 goto out;
2368 }
2369 res = parse_time_err(args[2], &timeout_retry, TIME_UNIT_MS);
2370 if (res) {
2371 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2372 file, linenum, *res, args[0]);
2373 err_code |= ERR_ALERT | ERR_FATAL;
2374 goto out;
2375 }
2376 curr_resolvers->timeout.retry = timeout_retry;
2377 } /* neither "nameserver" nor "resolvers" */
2378 else if (*args[0] != 0) {
2379 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2380 err_code |= ERR_ALERT | ERR_FATAL;
2381 goto out;
2382 }
2383
2384 out:
2385 free(errmsg);
2386 return err_code;
2387}
Simon Horman0d16a402015-01-30 11:22:58 +09002388
2389/*
William Lallemand51097192015-04-14 16:35:22 +02002390 * Parse a line in a <listen>, <frontend> or <backend> section.
Simon Horman0d16a402015-01-30 11:22:58 +09002391 * Returns the error code, 0 if OK, or any combination of :
2392 * - ERR_ABORT: must abort ASAP
2393 * - ERR_FATAL: we can continue parsing but not start the service
2394 * - ERR_WARN: a warning has been emitted
2395 * - ERR_ALERT: an alert has been emitted
2396 * Only the two first ones can stop processing, the two others are just
2397 * indicators.
2398 */
2399int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
2400{
2401 static struct mailers *curmailers = NULL;
2402 struct mailer *newmailer = NULL;
2403 const char *err;
2404 int err_code = 0;
2405 char *errmsg = NULL;
2406
2407 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
2408 if (!*args[1]) {
2409 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
2410 err_code |= ERR_ALERT | ERR_ABORT;
2411 goto out;
2412 }
2413
2414 err = invalid_char(args[1]);
2415 if (err) {
2416 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2417 file, linenum, *err, args[0], args[1]);
2418 err_code |= ERR_ALERT | ERR_ABORT;
2419 goto out;
2420 }
2421
2422 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
2423 /*
2424 * If there are two proxies with the same name only following
2425 * combinations are allowed:
2426 */
2427 if (strcmp(curmailers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002428 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 +09002429 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002430 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman0d16a402015-01-30 11:22:58 +09002431 }
2432 }
2433
2434 if ((curmailers = (struct mailers *)calloc(1, sizeof(struct mailers))) == NULL) {
2435 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2436 err_code |= ERR_ALERT | ERR_ABORT;
2437 goto out;
2438 }
2439
2440 curmailers->next = mailers;
2441 mailers = curmailers;
2442 curmailers->conf.file = strdup(file);
2443 curmailers->conf.line = linenum;
2444 curmailers->id = strdup(args[1]);
2445 }
2446 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
2447 struct sockaddr_storage *sk;
2448 int port1, port2;
2449 struct protocol *proto;
2450
2451 if (!*args[2]) {
2452 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2453 file, linenum, args[0]);
2454 err_code |= ERR_ALERT | ERR_FATAL;
2455 goto out;
2456 }
2457
2458 err = invalid_char(args[1]);
2459 if (err) {
2460 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2461 file, linenum, *err, args[1]);
2462 err_code |= ERR_ALERT | ERR_FATAL;
2463 goto out;
2464 }
2465
2466 if ((newmailer = (struct mailer *)calloc(1, sizeof(struct mailer))) == NULL) {
2467 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2468 err_code |= ERR_ALERT | ERR_ABORT;
2469 goto out;
2470 }
2471
2472 /* the mailers are linked backwards first */
2473 curmailers->count++;
2474 newmailer->next = curmailers->mailer_list;
2475 curmailers->mailer_list = newmailer;
2476 newmailer->mailers = curmailers;
2477 newmailer->conf.file = strdup(file);
2478 newmailer->conf.line = linenum;
2479
2480 newmailer->id = strdup(args[1]);
2481
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002482 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Simon Horman0d16a402015-01-30 11:22:58 +09002483 if (!sk) {
2484 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2485 err_code |= ERR_ALERT | ERR_FATAL;
2486 goto out;
2487 }
2488
2489 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002490 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2491 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002492 file, linenum, args[0], args[1]);
2493 err_code |= ERR_ALERT | ERR_FATAL;
2494 goto out;
2495 }
2496
2497 if (port1 != port2) {
2498 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2499 file, linenum, args[0], args[1], args[2]);
2500 err_code |= ERR_ALERT | ERR_FATAL;
2501 goto out;
2502 }
2503
2504 if (!port1) {
2505 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2506 file, linenum, args[0], args[1], args[2]);
2507 err_code |= ERR_ALERT | ERR_FATAL;
2508 goto out;
2509 }
2510
2511 newmailer->addr = *sk;
2512 newmailer->proto = proto;
2513 newmailer->xprt = &raw_sock;
2514 newmailer->sock_init_arg = NULL;
2515 } /* neither "mailer" nor "mailers" */
2516 else if (*args[0] != 0) {
2517 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2518 err_code |= ERR_ALERT | ERR_FATAL;
2519 goto out;
2520 }
2521
2522out:
2523 free(errmsg);
2524 return err_code;
2525}
2526
Simon Horman9dc49962015-01-30 11:22:59 +09002527static void free_email_alert(struct proxy *p)
2528{
2529 free(p->email_alert.mailers.name);
2530 p->email_alert.mailers.name = NULL;
2531 free(p->email_alert.from);
2532 p->email_alert.from = NULL;
2533 free(p->email_alert.to);
2534 p->email_alert.to = NULL;
2535 free(p->email_alert.myhostname);
2536 p->email_alert.myhostname = NULL;
2537}
2538
Willy Tarreau3842f002009-06-14 11:39:52 +02002539int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002540{
2541 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002542 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002543 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002544 int rc;
2545 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002546 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002547 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002548 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002549 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002550 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002551
Willy Tarreau977b8e42006-12-29 14:19:17 +01002552 if (!strcmp(args[0], "listen"))
2553 rc = PR_CAP_LISTEN;
2554 else if (!strcmp(args[0], "frontend"))
2555 rc = PR_CAP_FE | PR_CAP_RS;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02002556 else if (!strcmp(args[0], "backend"))
Willy Tarreau977b8e42006-12-29 14:19:17 +01002557 rc = PR_CAP_BE | PR_CAP_RS;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002558 else
2559 rc = PR_CAP_NONE;
2560
2561 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002562 if (!*args[1]) {
2563 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
2564 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
2565 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002566 err_code |= ERR_ALERT | ERR_ABORT;
2567 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002568 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002569
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002570 err = invalid_char(args[1]);
2571 if (err) {
2572 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2573 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002574 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002575 }
2576
Willy Tarreau8f50b682015-05-26 11:45:02 +02002577 curproxy = (rc & PR_CAP_FE) ? proxy_fe_by_name(args[1]) : proxy_be_by_name(args[1]);
2578 if (curproxy) {
2579 Alert("Parsing [%s:%d]: %s '%s' has the same name as %s '%s' declared at %s:%d.\n",
2580 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2581 curproxy->id, curproxy->conf.file, curproxy->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002582 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002583 }
2584
Willy Tarreaubaaee002006-06-26 02:48:02 +02002585 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
2586 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002587 err_code |= ERR_ALERT | ERR_ABORT;
2588 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002589 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002590
Willy Tarreau97cb7802010-01-03 20:23:58 +01002591 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002592 curproxy->next = proxy;
2593 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002594 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2595 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002596 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002597 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002598 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002599 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002600
William Lallemand6e62fb62015-04-28 16:55:23 +02002601 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2602 if (curproxy->cap & PR_CAP_FE)
2603 Alert("parsing [%s:%d] : please use the 'bind' keyword for listening addresses.\n", file, linenum);
2604 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002605 }
2606
2607 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002608 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002609 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002610
Willy Tarreaubaaee002006-06-26 02:48:02 +02002611 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002612 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002613 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002614 curproxy->no_options = defproxy.no_options;
2615 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002616 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002617 curproxy->except_net = defproxy.except_net;
2618 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002619 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002620 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002621
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002622 if (defproxy.fwdfor_hdr_len) {
2623 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2624 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2625 }
2626
Willy Tarreaub86db342009-11-30 11:50:16 +01002627 if (defproxy.orgto_hdr_len) {
2628 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2629 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2630 }
2631
Mark Lamourinec2247f02012-01-04 13:02:01 -05002632 if (defproxy.server_id_hdr_len) {
2633 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2634 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2635 }
2636
Willy Tarreau977b8e42006-12-29 14:19:17 +01002637 if (curproxy->cap & PR_CAP_FE) {
2638 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002639 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002640 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002641
2642 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002643 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2644 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002645
2646 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2647 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002648
Willy Tarreau977b8e42006-12-29 14:19:17 +01002649 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002650 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002651 curproxy->fullconn = defproxy.fullconn;
2652 curproxy->conn_retries = defproxy.conn_retries;
Joseph Lynch726ab712015-05-11 23:25:34 -07002653 curproxy->redispatch_after = defproxy.redispatch_after;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002654 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002655
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002656 if (defproxy.check_req) {
2657 curproxy->check_req = calloc(1, defproxy.check_len);
2658 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2659 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002660 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002661
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002662 if (defproxy.expect_str) {
2663 curproxy->expect_str = strdup(defproxy.expect_str);
2664 if (defproxy.expect_regex) {
2665 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002666 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2667 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002668 }
2669 }
2670
Willy Tarreau67402132012-05-31 20:40:20 +02002671 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002672 if (defproxy.cookie_name)
2673 curproxy->cookie_name = strdup(defproxy.cookie_name);
2674 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002675 if (defproxy.cookie_domain)
2676 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002677
Willy Tarreau31936852010-10-06 16:59:56 +02002678 if (defproxy.cookie_maxidle)
2679 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2680
2681 if (defproxy.cookie_maxlife)
2682 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2683
Emeric Brun647caf12009-06-30 17:57:00 +02002684 if (defproxy.rdp_cookie_name)
2685 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2686 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2687
Willy Tarreau01732802007-11-01 22:48:15 +01002688 if (defproxy.url_param_name)
2689 curproxy->url_param_name = strdup(defproxy.url_param_name);
2690 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002691
Benoitaffb4812009-03-25 13:02:10 +01002692 if (defproxy.hh_name)
2693 curproxy->hh_name = strdup(defproxy.hh_name);
2694 curproxy->hh_len = defproxy.hh_len;
2695 curproxy->hh_match_domain = defproxy.hh_match_domain;
2696
Willy Tarreauef9a3602012-12-08 22:29:20 +01002697 if (defproxy.conn_src.iface_name)
2698 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2699 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002700 curproxy->conn_src.opts = defproxy.conn_src.opts;
Willy Tarreau29fbe512015-08-20 19:35:14 +02002701#if defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002702 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002703#endif
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02002704 curproxy->load_server_state_from_file = defproxy.load_server_state_from_file;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002705 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002706
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002707 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002708 if (defproxy.capture_name)
2709 curproxy->capture_name = strdup(defproxy.capture_name);
2710 curproxy->capture_namelen = defproxy.capture_namelen;
2711 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002712 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002713
Willy Tarreau977b8e42006-12-29 14:19:17 +01002714 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002715 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002716 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002717 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002718 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002719 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002720 curproxy->mon_net = defproxy.mon_net;
2721 curproxy->mon_mask = defproxy.mon_mask;
2722 if (defproxy.monitor_uri)
2723 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2724 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002725 if (defproxy.defbe.name)
2726 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002727
2728 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002729 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2730 if (curproxy->conf.logformat_string &&
2731 curproxy->conf.logformat_string != default_http_log_format &&
2732 curproxy->conf.logformat_string != default_tcp_log_format &&
2733 curproxy->conf.logformat_string != clf_http_log_format)
2734 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2735
2736 if (defproxy.conf.lfs_file) {
2737 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2738 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2739 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002740
2741 /* get either a pointer to the logformat string for RFC5424 structured-data or a copy of it */
2742 curproxy->conf.logformat_sd_string = defproxy.conf.logformat_sd_string;
2743 if (curproxy->conf.logformat_sd_string &&
2744 curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
2745 curproxy->conf.logformat_sd_string = strdup(curproxy->conf.logformat_sd_string);
2746
2747 if (defproxy.conf.lfsd_file) {
2748 curproxy->conf.lfsd_file = strdup(defproxy.conf.lfsd_file);
2749 curproxy->conf.lfsd_line = defproxy.conf.lfsd_line;
2750 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002751 }
2752
2753 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002754 curproxy->timeout.connect = defproxy.timeout.connect;
2755 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002756 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002757 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002758 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002759 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002760 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002761 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002762 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002763 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002764 }
2765
Willy Tarreaubaaee002006-06-26 02:48:02 +02002766 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002767 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002768
2769 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002770 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002771 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002772 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002773 LIST_INIT(&node->list);
2774 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2775 }
2776
Willy Tarreau62a61232013-04-12 18:13:46 +02002777 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2778 if (curproxy->conf.uniqueid_format_string)
2779 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2780
Dragan Dosen43885c72015-10-01 13:18:13 +02002781 chunk_dup(&curproxy->log_tag, &defproxy.log_tag);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002782
Willy Tarreau62a61232013-04-12 18:13:46 +02002783 if (defproxy.conf.uif_file) {
2784 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2785 curproxy->conf.uif_line = defproxy.conf.uif_line;
2786 }
William Lallemanda73203e2012-03-12 12:48:57 +01002787
2788 /* copy default header unique id */
2789 if (defproxy.header_unique_id)
2790 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2791
William Lallemand82fe75c2012-10-23 10:25:10 +02002792 /* default compression options */
2793 if (defproxy.comp != NULL) {
2794 curproxy->comp = calloc(1, sizeof(struct comp));
2795 curproxy->comp->algos = defproxy.comp->algos;
2796 curproxy->comp->types = defproxy.comp->types;
2797 }
2798
Willy Tarreaubaaee002006-06-26 02:48:02 +02002799 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002800 curproxy->conf.used_listener_id = EB_ROOT;
2801 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002802
Simon Horman98637e52014-06-20 12:30:16 +09002803 if (defproxy.check_path)
2804 curproxy->check_path = strdup(defproxy.check_path);
2805 if (defproxy.check_command)
2806 curproxy->check_command = strdup(defproxy.check_command);
2807
Simon Horman9dc49962015-01-30 11:22:59 +09002808 if (defproxy.email_alert.mailers.name)
2809 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2810 if (defproxy.email_alert.from)
2811 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2812 if (defproxy.email_alert.to)
2813 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2814 if (defproxy.email_alert.myhostname)
2815 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09002816 curproxy->email_alert.level = defproxy.email_alert.level;
Cyril Bonté7e084702015-12-04 03:07:06 +01002817 curproxy->email_alert.set = defproxy.email_alert.set;
Simon Horman9dc49962015-01-30 11:22:59 +09002818
Willy Tarreau93893792009-07-23 13:19:11 +02002819 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002820 }
2821 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2822 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002823 /* FIXME-20070101: we should do this too at the end of the
2824 * config parsing to free all default values.
2825 */
William Lallemand6e62fb62015-04-28 16:55:23 +02002826 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2827 err_code |= ERR_ABORT;
2828 goto out;
2829 }
2830
Willy Tarreaua534fea2008-08-03 12:19:50 +02002831 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002832 free(defproxy.check_command);
2833 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002834 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002835 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002836 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002837 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002838 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002839 free(defproxy.capture_name);
2840 free(defproxy.monitor_uri);
2841 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002842 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002843 free(defproxy.fwdfor_hdr_name);
2844 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002845 free(defproxy.orgto_hdr_name);
2846 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002847 free(defproxy.server_id_hdr_name);
2848 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002849 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002850 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002851 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002852 free(defproxy.expect_regex);
2853 defproxy.expect_regex = NULL;
2854 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002855
Willy Tarreau62a61232013-04-12 18:13:46 +02002856 if (defproxy.conf.logformat_string != default_http_log_format &&
2857 defproxy.conf.logformat_string != default_tcp_log_format &&
2858 defproxy.conf.logformat_string != clf_http_log_format)
2859 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002860
Willy Tarreau62a61232013-04-12 18:13:46 +02002861 free(defproxy.conf.uniqueid_format_string);
2862 free(defproxy.conf.lfs_file);
2863 free(defproxy.conf.uif_file);
Dragan Dosen43885c72015-10-01 13:18:13 +02002864 chunk_destroy(&defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09002865 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02002866
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002867 if (defproxy.conf.logformat_sd_string != default_rfc5424_sd_log_format)
2868 free(defproxy.conf.logformat_sd_string);
2869 free(defproxy.conf.lfsd_file);
2870
Willy Tarreaua534fea2008-08-03 12:19:50 +02002871 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002872 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002873
Willy Tarreaubaaee002006-06-26 02:48:02 +02002874 /* we cannot free uri_auth because it might already be used */
2875 init_default_instance();
2876 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002877 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2878 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002879 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002880 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002881 }
2882 else if (curproxy == NULL) {
2883 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002884 err_code |= ERR_ALERT | ERR_FATAL;
2885 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002886 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002887
2888 /* update the current file and line being parsed */
2889 curproxy->conf.args.file = curproxy->conf.file;
2890 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002891
2892 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002893 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2894 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2895 if (err_code & ERR_FATAL)
2896 goto out;
2897 }
2898 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002899 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002900 int cur_arg;
2901
Willy Tarreaubaaee002006-06-26 02:48:02 +02002902 if (curproxy == &defproxy) {
2903 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002904 err_code |= ERR_ALERT | ERR_FATAL;
2905 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002906 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002907 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002908 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002909
Willy Tarreau24709282013-03-10 21:32:12 +01002910 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002911 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002912 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002913 err_code |= ERR_ALERT | ERR_FATAL;
2914 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002915 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002916
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002917 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002918
2919 /* use default settings for unix sockets */
2920 bind_conf->ux.uid = global.unix_bind.ux.uid;
2921 bind_conf->ux.gid = global.unix_bind.ux.gid;
2922 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002923
2924 /* NOTE: the following line might create several listeners if there
2925 * are comma-separated IPs or port ranges. So all further processing
2926 * will have to be applied to all listeners created after last_listen.
2927 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002928 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2929 if (errmsg && *errmsg) {
2930 indent_msg(&errmsg, 2);
2931 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002932 }
2933 else
2934 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2935 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002936 err_code |= ERR_ALERT | ERR_FATAL;
2937 goto out;
2938 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002939
Willy Tarreau4348fad2012-09-20 16:48:07 +02002940 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2941 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002942 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002943 }
2944
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002945 cur_arg = 2;
2946 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002947 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002948 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002949 char *err;
2950
Willy Tarreau26982662012-09-12 23:17:10 +02002951 kw = bind_find_kw(args[cur_arg]);
2952 if (kw) {
2953 char *err = NULL;
2954 int code;
2955
2956 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002957 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2958 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002959 cur_arg += 1 + kw->skip ;
2960 err_code |= ERR_ALERT | ERR_FATAL;
2961 goto out;
2962 }
2963
Willy Tarreau4348fad2012-09-20 16:48:07 +02002964 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002965 err_code |= code;
2966
2967 if (code) {
2968 if (err && *err) {
2969 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002970 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002971 }
2972 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002973 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2974 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002975 if (code & ERR_FATAL) {
2976 free(err);
2977 cur_arg += 1 + kw->skip;
2978 goto out;
2979 }
2980 }
2981 free(err);
2982 cur_arg += 1 + kw->skip;
2983 continue;
2984 }
2985
Willy Tarreau8638f482012-09-18 18:01:17 +02002986 err = NULL;
2987 if (!bind_dumped) {
2988 bind_dump_kws(&err);
2989 indent_msg(&err, 4);
2990 bind_dumped = 1;
2991 }
2992
2993 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2994 file, linenum, args[0], args[1], args[cur_arg],
2995 err ? " Registered keywords :" : "", err ? err : "");
2996 free(err);
2997
Willy Tarreau93893792009-07-23 13:19:11 +02002998 err_code |= ERR_ALERT | ERR_FATAL;
2999 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01003000 }
Willy Tarreau93893792009-07-23 13:19:11 +02003001 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003002 }
3003 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01003004 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003005 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
3006 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003007 err_code |= ERR_ALERT | ERR_FATAL;
3008 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003009 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003010 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003011 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003012
Willy Tarreaubaaee002006-06-26 02:48:02 +02003013 /* flush useless bits */
3014 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02003015 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003016 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02003017 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003018 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003019 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003020
William Lallemanddf1425a2015-04-28 20:17:49 +02003021 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3022 goto out;
3023
Willy Tarreau1c47f852006-07-09 08:22:27 +02003024 if (!*args[1]) {
3025 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
3026 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003027 err_code |= ERR_ALERT | ERR_FATAL;
3028 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003029 }
3030
Willy Tarreaua534fea2008-08-03 12:19:50 +02003031 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003032 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02003033 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003034 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02003035 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
3036
Willy Tarreau93893792009-07-23 13:19:11 +02003037 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003038 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003039 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
William Lallemanddf1425a2015-04-28 20:17:49 +02003040 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3041 goto out;
3042
Willy Tarreaubaaee002006-06-26 02:48:02 +02003043 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
3044 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
3045 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
3046 else {
3047 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003048 err_code |= ERR_ALERT | ERR_FATAL;
3049 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003050 }
3051 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003052 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003053 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003054
3055 if (curproxy == &defproxy) {
3056 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3057 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003058 err_code |= ERR_ALERT | ERR_FATAL;
3059 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003060 }
3061
William Lallemanddf1425a2015-04-28 20:17:49 +02003062 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3063 goto out;
3064
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003065 if (!*args[1]) {
3066 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3067 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003068 err_code |= ERR_ALERT | ERR_FATAL;
3069 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003070 }
3071
3072 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003073 curproxy->conf.id.key = curproxy->uuid;
Willy Tarreau0d1fdf72015-05-27 16:44:02 +02003074 curproxy->options |= PR_O_FORCED_ID;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003075
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003076 if (curproxy->uuid <= 0) {
3077 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003078 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003079 err_code |= ERR_ALERT | ERR_FATAL;
3080 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003081 }
3082
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003083 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
3084 if (node) {
3085 struct proxy *target = container_of(node, struct proxy, conf.id);
3086 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
3087 file, linenum, proxy_type_str(curproxy), curproxy->id,
3088 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
3089 err_code |= ERR_ALERT | ERR_FATAL;
3090 goto out;
3091 }
3092 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003093 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003094 else if (!strcmp(args[0], "description")) {
3095 int i, len=0;
3096 char *d;
3097
Cyril Bonté99ed3272010-01-24 23:29:44 +01003098 if (curproxy == &defproxy) {
3099 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3100 file, linenum, args[0]);
3101 err_code |= ERR_ALERT | ERR_FATAL;
3102 goto out;
3103 }
3104
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003105 if (!*args[1]) {
3106 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
3107 file, linenum, args[0]);
3108 return -1;
3109 }
3110
Willy Tarreau348acfe2014-04-14 15:00:39 +02003111 for (i = 1; *args[i]; i++)
3112 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003113
3114 d = (char *)calloc(1, len);
3115 curproxy->desc = d;
3116
Willy Tarreau348acfe2014-04-14 15:00:39 +02003117 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
3118 for (i = 2; *args[i]; i++)
3119 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003120
3121 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003122 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
William Lallemanddf1425a2015-04-28 20:17:49 +02003123 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3124 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003125 curproxy->state = PR_STSTOPPED;
3126 }
3127 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
William Lallemanddf1425a2015-04-28 20:17:49 +02003128 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3129 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003130 curproxy->state = PR_STNEW;
3131 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003132 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
3133 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003134 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003135
3136 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003137 unsigned int low, high;
3138
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003139 if (strcmp(args[cur_arg], "all") == 0) {
3140 set = 0;
3141 break;
3142 }
3143 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003144 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003145 }
3146 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003147 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003148 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01003149 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003150 char *dash = strchr(args[cur_arg], '-');
3151
3152 low = high = str2uic(args[cur_arg]);
3153 if (dash)
3154 high = str2uic(dash + 1);
3155
3156 if (high < low) {
3157 unsigned int swap = low;
3158 low = high;
3159 high = swap;
3160 }
3161
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003162 if (low < 1 || high > LONGBITS) {
3163 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
3164 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02003165 err_code |= ERR_ALERT | ERR_FATAL;
3166 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003167 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01003168 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003169 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003170 }
3171 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003172 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
3173 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003174 err_code |= ERR_ALERT | ERR_FATAL;
3175 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003176 }
3177 cur_arg++;
3178 }
3179 curproxy->bind_proc = set;
3180 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003181 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02003182 if (curproxy == &defproxy) {
3183 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003184 err_code |= ERR_ALERT | ERR_FATAL;
3185 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003186 }
3187
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003188 err = invalid_char(args[1]);
3189 if (err) {
3190 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
3191 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003192 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003193 }
3194
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01003195 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003196 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
3197 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003198 err_code |= ERR_ALERT | ERR_FATAL;
3199 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003200 }
3201 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003202 else if (!strcmp(args[0], "cookie")) { /* cookie name */
3203 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003204
Willy Tarreau977b8e42006-12-29 14:19:17 +01003205 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003206 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003207
Willy Tarreaubaaee002006-06-26 02:48:02 +02003208 if (*(args[1]) == 0) {
3209 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
3210 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003211 err_code |= ERR_ALERT | ERR_FATAL;
3212 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003213 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003214
Willy Tarreau67402132012-05-31 20:40:20 +02003215 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003216 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01003217 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003218 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003219 curproxy->cookie_name = strdup(args[1]);
3220 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003221
Willy Tarreaubaaee002006-06-26 02:48:02 +02003222 cur_arg = 2;
3223 while (*(args[cur_arg])) {
3224 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003225 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003226 }
3227 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003228 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003229 }
3230 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003231 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003232 }
3233 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003234 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003235 }
3236 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003237 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003238 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003239 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003240 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003241 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003242 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003243 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003244 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02003245 else if (!strcmp(args[cur_arg], "httponly")) {
3246 curproxy->ck_opts |= PR_CK_HTTPONLY;
3247 }
3248 else if (!strcmp(args[cur_arg], "secure")) {
3249 curproxy->ck_opts |= PR_CK_SECURE;
3250 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003251 else if (!strcmp(args[cur_arg], "domain")) {
3252 if (!*args[cur_arg + 1]) {
3253 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
3254 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003255 err_code |= ERR_ALERT | ERR_FATAL;
3256 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003257 }
3258
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003259 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003260 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003261 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
3262 " dots nor does not start with a dot."
3263 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003264 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003265 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003266 }
3267
3268 err = invalid_domainchar(args[cur_arg + 1]);
3269 if (err) {
3270 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
3271 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003272 err_code |= ERR_ALERT | ERR_FATAL;
3273 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003274 }
3275
Willy Tarreau68a897b2009-12-03 23:28:34 +01003276 if (!curproxy->cookie_domain) {
3277 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
3278 } else {
3279 /* one domain was already specified, add another one by
3280 * building the string which will be returned along with
3281 * the cookie.
3282 */
3283 char *new_ptr;
3284 int new_len = strlen(curproxy->cookie_domain) +
3285 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
3286 new_ptr = malloc(new_len);
3287 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
3288 free(curproxy->cookie_domain);
3289 curproxy->cookie_domain = new_ptr;
3290 }
Willy Tarreau31936852010-10-06 16:59:56 +02003291 cur_arg++;
3292 }
3293 else if (!strcmp(args[cur_arg], "maxidle")) {
3294 unsigned int maxidle;
3295 const char *res;
3296
3297 if (!*args[cur_arg + 1]) {
3298 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
3299 file, linenum, args[cur_arg]);
3300 err_code |= ERR_ALERT | ERR_FATAL;
3301 goto out;
3302 }
3303
3304 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
3305 if (res) {
3306 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3307 file, linenum, *res, args[cur_arg]);
3308 err_code |= ERR_ALERT | ERR_FATAL;
3309 goto out;
3310 }
3311 curproxy->cookie_maxidle = maxidle;
3312 cur_arg++;
3313 }
3314 else if (!strcmp(args[cur_arg], "maxlife")) {
3315 unsigned int maxlife;
3316 const char *res;
3317
3318 if (!*args[cur_arg + 1]) {
3319 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
3320 file, linenum, args[cur_arg]);
3321 err_code |= ERR_ALERT | ERR_FATAL;
3322 goto out;
3323 }
3324
3325 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
3326 if (res) {
3327 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3328 file, linenum, *res, args[cur_arg]);
3329 err_code |= ERR_ALERT | ERR_FATAL;
3330 goto out;
3331 }
3332 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003333 cur_arg++;
3334 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003335 else {
Willy Tarreau31936852010-10-06 16:59:56 +02003336 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 +02003337 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003338 err_code |= ERR_ALERT | ERR_FATAL;
3339 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003340 }
3341 cur_arg++;
3342 }
Willy Tarreau67402132012-05-31 20:40:20 +02003343 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003344 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
3345 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003346 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003347 }
3348
Willy Tarreau67402132012-05-31 20:40:20 +02003349 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003350 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
3351 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003352 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003353 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003354
Willy Tarreau67402132012-05-31 20:40:20 +02003355 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003356 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
3357 file, linenum);
3358 err_code |= ERR_ALERT | ERR_FATAL;
3359 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003360 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09003361 else if (!strcmp(args[0], "email-alert")) {
3362 if (*(args[1]) == 0) {
3363 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3364 file, linenum, args[0]);
3365 err_code |= ERR_ALERT | ERR_FATAL;
3366 goto out;
3367 }
3368
3369 if (!strcmp(args[1], "from")) {
3370 if (*(args[1]) == 0) {
3371 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3372 file, linenum, args[1]);
3373 err_code |= ERR_ALERT | ERR_FATAL;
3374 goto out;
3375 }
3376 free(curproxy->email_alert.from);
3377 curproxy->email_alert.from = strdup(args[2]);
3378 }
3379 else if (!strcmp(args[1], "mailers")) {
3380 if (*(args[1]) == 0) {
3381 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3382 file, linenum, args[1]);
3383 err_code |= ERR_ALERT | ERR_FATAL;
3384 goto out;
3385 }
3386 free(curproxy->email_alert.mailers.name);
3387 curproxy->email_alert.mailers.name = strdup(args[2]);
3388 }
3389 else if (!strcmp(args[1], "myhostname")) {
3390 if (*(args[1]) == 0) {
3391 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3392 file, linenum, args[1]);
3393 err_code |= ERR_ALERT | ERR_FATAL;
3394 goto out;
3395 }
3396 free(curproxy->email_alert.myhostname);
3397 curproxy->email_alert.myhostname = strdup(args[2]);
3398 }
Simon Horman64e34162015-02-06 11:11:57 +09003399 else if (!strcmp(args[1], "level")) {
3400 curproxy->email_alert.level = get_log_level(args[2]);
3401 if (curproxy->email_alert.level < 0) {
3402 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
3403 file, linenum, args[1], args[2]);
3404 err_code |= ERR_ALERT | ERR_FATAL;
3405 goto out;
3406 }
3407 }
Simon Horman9dc49962015-01-30 11:22:59 +09003408 else if (!strcmp(args[1], "to")) {
3409 if (*(args[1]) == 0) {
3410 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3411 file, linenum, args[1]);
3412 err_code |= ERR_ALERT | ERR_FATAL;
3413 goto out;
3414 }
3415 free(curproxy->email_alert.to);
3416 curproxy->email_alert.to = strdup(args[2]);
3417 }
3418 else {
3419 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
3420 file, linenum, args[1]);
3421 err_code |= ERR_ALERT | ERR_FATAL;
3422 goto out;
3423 }
Simon Horman64e34162015-02-06 11:11:57 +09003424 /* Indicate that the email_alert is at least partially configured */
3425 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09003426 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09003427 else if (!strcmp(args[0], "external-check")) {
3428 if (*(args[1]) == 0) {
3429 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3430 file, linenum, args[0]);
3431 err_code |= ERR_ALERT | ERR_FATAL;
3432 goto out;
3433 }
3434
3435 if (!strcmp(args[1], "command")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003436 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003437 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003438 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003439 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3440 file, linenum, args[1]);
3441 err_code |= ERR_ALERT | ERR_FATAL;
3442 goto out;
3443 }
3444 free(curproxy->check_command);
3445 curproxy->check_command = strdup(args[2]);
3446 }
3447 else if (!strcmp(args[1], "path")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003448 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003449 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003450 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003451 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3452 file, linenum, args[1]);
3453 err_code |= ERR_ALERT | ERR_FATAL;
3454 goto out;
3455 }
3456 free(curproxy->check_path);
3457 curproxy->check_path = strdup(args[2]);
3458 }
3459 else {
3460 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
3461 file, linenum, args[1]);
3462 err_code |= ERR_ALERT | ERR_FATAL;
3463 goto out;
3464 }
3465 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02003466 else if (!strcmp(args[0], "persist")) { /* persist */
3467 if (*(args[1]) == 0) {
3468 Alert("parsing [%s:%d] : missing persist method.\n",
3469 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003470 err_code |= ERR_ALERT | ERR_FATAL;
3471 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003472 }
3473
3474 if (!strncmp(args[1], "rdp-cookie", 10)) {
3475 curproxy->options2 |= PR_O2_RDPC_PRST;
3476
Emeric Brunb982a3d2010-01-04 15:45:53 +01003477 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003478 const char *beg, *end;
3479
3480 beg = args[1] + 11;
3481 end = strchr(beg, ')');
3482
William Lallemanddf1425a2015-04-28 20:17:49 +02003483 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3484 goto out;
3485
Emeric Brun647caf12009-06-30 17:57:00 +02003486 if (!end || end == beg) {
3487 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3488 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003489 err_code |= ERR_ALERT | ERR_FATAL;
3490 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003491 }
3492
3493 free(curproxy->rdp_cookie_name);
3494 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3495 curproxy->rdp_cookie_len = end-beg;
3496 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003497 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003498 free(curproxy->rdp_cookie_name);
3499 curproxy->rdp_cookie_name = strdup("msts");
3500 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3501 }
3502 else { /* syntax */
3503 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3504 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003505 err_code |= ERR_ALERT | ERR_FATAL;
3506 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003507 }
3508 }
3509 else {
3510 Alert("parsing [%s:%d] : unknown persist method.\n",
3511 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003512 err_code |= ERR_ALERT | ERR_FATAL;
3513 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003514 }
3515 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003516 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreau6db62c52015-08-10 19:04:29 +02003517 Alert("parsing [%s:%d] : '%s' is not supported anymore, please check the documentation.\n", file, linenum, args[0]);
3518 err_code |= ERR_ALERT | ERR_FATAL;
3519 goto out;
3520 }
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02003521 else if (!strcmp(args[0], "load-server-state-from-file")) {
3522 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3523 err_code |= ERR_WARN;
3524 if (!strcmp(args[1], "global")) { /* use the file pointed to by global server-state-file directive */
3525 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_GLOBAL;
3526 }
3527 else if (!strcmp(args[1], "local")) { /* use the server-state-file-name variable to locate the server-state file */
3528 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_LOCAL;
3529 }
3530 else if (!strcmp(args[1], "none")) { /* don't use server-state-file directive for this backend */
3531 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
3532 }
3533 else {
3534 Alert("parsing [%s:%d] : '%s' expects 'global', 'local' or 'none'. Got '%s'\n",
3535 file, linenum, args[0], args[1]);
3536 err_code |= ERR_ALERT | ERR_FATAL;
3537 goto out;
3538 }
3539 }
3540 else if (!strcmp(args[0], "server-state-file-name")) {
3541 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3542 err_code |= ERR_WARN;
3543 if (*(args[1]) == 0) {
3544 Alert("parsing [%s:%d] : '%s' expects 'use-backend-name' or a string. Got no argument\n",
3545 file, linenum, args[0]);
3546 err_code |= ERR_ALERT | ERR_FATAL;
3547 goto out;
3548 }
3549 else if (!strcmp(args[1], "use-backend-name"))
3550 curproxy->server_state_file_name = strdup(curproxy->id);
3551 else
3552 curproxy->server_state_file_name = strdup(args[1]);
3553 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003554 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003555 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003556 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003557
Willy Tarreaubaaee002006-06-26 02:48:02 +02003558 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003559 if (curproxy == &defproxy) {
3560 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3561 err_code |= ERR_ALERT | ERR_FATAL;
3562 goto out;
3563 }
3564
William Lallemand1a748ae2015-05-19 16:37:23 +02003565 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3566 goto out;
3567
Willy Tarreaubaaee002006-06-26 02:48:02 +02003568 if (*(args[4]) == 0) {
3569 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3570 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003571 err_code |= ERR_ALERT | ERR_FATAL;
3572 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003573 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003574 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003575 curproxy->capture_name = strdup(args[2]);
3576 curproxy->capture_namelen = strlen(curproxy->capture_name);
3577 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003578 curproxy->to_log |= LW_COOKIE;
3579 }
3580 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3581 struct cap_hdr *hdr;
3582
3583 if (curproxy == &defproxy) {
3584 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 +02003585 err_code |= ERR_ALERT | ERR_FATAL;
3586 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003587 }
3588
William Lallemand1a748ae2015-05-19 16:37:23 +02003589 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3590 goto out;
3591
Willy Tarreaubaaee002006-06-26 02:48:02 +02003592 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3593 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3594 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003595 err_code |= ERR_ALERT | ERR_FATAL;
3596 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003597 }
3598
3599 hdr = calloc(sizeof(struct cap_hdr), 1);
3600 hdr->next = curproxy->req_cap;
3601 hdr->name = strdup(args[3]);
3602 hdr->namelen = strlen(args[3]);
3603 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003604 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003605 hdr->index = curproxy->nb_req_cap++;
3606 curproxy->req_cap = hdr;
3607 curproxy->to_log |= LW_REQHDR;
3608 }
3609 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3610 struct cap_hdr *hdr;
3611
3612 if (curproxy == &defproxy) {
3613 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 +02003614 err_code |= ERR_ALERT | ERR_FATAL;
3615 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003616 }
3617
William Lallemand1a748ae2015-05-19 16:37:23 +02003618 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3619 goto out;
3620
Willy Tarreaubaaee002006-06-26 02:48:02 +02003621 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3622 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3623 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003624 err_code |= ERR_ALERT | ERR_FATAL;
3625 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003626 }
3627 hdr = calloc(sizeof(struct cap_hdr), 1);
3628 hdr->next = curproxy->rsp_cap;
3629 hdr->name = strdup(args[3]);
3630 hdr->namelen = strlen(args[3]);
3631 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003632 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003633 hdr->index = curproxy->nb_rsp_cap++;
3634 curproxy->rsp_cap = hdr;
3635 curproxy->to_log |= LW_RSPHDR;
3636 }
3637 else {
3638 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3639 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003640 err_code |= ERR_ALERT | ERR_FATAL;
3641 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003642 }
3643 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003644 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003645 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003646 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003647
William Lallemanddf1425a2015-04-28 20:17:49 +02003648 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3649 goto out;
3650
Willy Tarreaubaaee002006-06-26 02:48:02 +02003651 if (*(args[1]) == 0) {
3652 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3653 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003654 err_code |= ERR_ALERT | ERR_FATAL;
3655 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003656 }
3657 curproxy->conn_retries = atol(args[1]);
3658 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003659 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003660 struct act_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003661
3662 if (curproxy == &defproxy) {
3663 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3664 err_code |= ERR_ALERT | ERR_FATAL;
3665 goto out;
3666 }
3667
Willy Tarreau20b0de52012-12-24 15:45:22 +01003668 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003669 !LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003670 (LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3671 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_DENY ||
3672 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REDIR ||
3673 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REQ_AUTH)) {
Willy Tarreau20b0de52012-12-24 15:45:22 +01003674 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 +01003675 file, linenum, args[0]);
3676 err_code |= ERR_WARN;
3677 }
3678
Willy Tarreauff011f22011-01-06 17:51:27 +01003679 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003680
Willy Tarreauff011f22011-01-06 17:51:27 +01003681 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003682 err_code |= ERR_ALERT | ERR_ABORT;
3683 goto out;
3684 }
3685
Willy Tarreau5002f572014-04-23 01:32:02 +02003686 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003687 err_code |= warnif_cond_conflicts(rule->cond,
3688 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3689 file, linenum);
3690
Willy Tarreauff011f22011-01-06 17:51:27 +01003691 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003692 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003693 else if (!strcmp(args[0], "http-response")) { /* response access control */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003694 struct act_rule *rule;
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003695
3696 if (curproxy == &defproxy) {
3697 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3698 err_code |= ERR_ALERT | ERR_FATAL;
3699 goto out;
3700 }
3701
3702 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003703 !LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003704 (LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3705 LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_DENY)) {
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003706 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3707 file, linenum, args[0]);
3708 err_code |= ERR_WARN;
3709 }
3710
3711 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3712
3713 if (!rule) {
3714 err_code |= ERR_ALERT | ERR_ABORT;
3715 goto out;
3716 }
3717
3718 err_code |= warnif_cond_conflicts(rule->cond,
3719 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3720 file, linenum);
3721
3722 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3723 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003724 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3725 /* set the header name and length into the proxy structure */
3726 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3727 err_code |= ERR_WARN;
3728
3729 if (!*args[1]) {
3730 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3731 file, linenum, args[0]);
3732 err_code |= ERR_ALERT | ERR_FATAL;
3733 goto out;
3734 }
3735
3736 /* set the desired header name */
3737 free(curproxy->server_id_hdr_name);
3738 curproxy->server_id_hdr_name = strdup(args[1]);
3739 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3740 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003741 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003742 struct act_rule *rule;
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003743
Willy Tarreaub099aca2008-10-12 17:26:37 +02003744 if (curproxy == &defproxy) {
3745 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003746 err_code |= ERR_ALERT | ERR_FATAL;
3747 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003748 }
3749
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003750 /* emulate "block" using "http-request block". Since these rules are supposed to
3751 * be processed before all http-request rules, we put them into their own list
3752 * and will insert them at the end.
3753 */
3754 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3755 if (!rule) {
3756 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003757 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003758 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003759 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3760 err_code |= warnif_cond_conflicts(rule->cond,
3761 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3762 file, linenum);
3763 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003764
3765 if (!already_warned(WARN_BLOCK_DEPRECATED))
3766 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]);
3767
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003768 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003769 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003770 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003771
Cyril Bonté99ed3272010-01-24 23:29:44 +01003772 if (curproxy == &defproxy) {
3773 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3774 err_code |= ERR_ALERT | ERR_FATAL;
3775 goto out;
3776 }
3777
Willy Tarreaube4653b2015-05-28 15:26:58 +02003778 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003779 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3780 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003781 err_code |= ERR_ALERT | ERR_FATAL;
3782 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003783 }
3784
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003785 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003786 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003787 err_code |= warnif_cond_conflicts(rule->cond,
3788 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3789 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003790 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003791 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003792 struct switching_rule *rule;
3793
Willy Tarreaub099aca2008-10-12 17:26:37 +02003794 if (curproxy == &defproxy) {
3795 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003796 err_code |= ERR_ALERT | ERR_FATAL;
3797 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003798 }
3799
Willy Tarreau55ea7572007-06-17 19:56:27 +02003800 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003801 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003802
3803 if (*(args[1]) == 0) {
3804 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003805 err_code |= ERR_ALERT | ERR_FATAL;
3806 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003807 }
3808
Willy Tarreauf51658d2014-04-23 01:21:56 +02003809 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3810 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3811 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3812 file, linenum, errmsg);
3813 err_code |= ERR_ALERT | ERR_FATAL;
3814 goto out;
3815 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003816
Willy Tarreauf51658d2014-04-23 01:21:56 +02003817 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003818 }
3819
3820 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
3821 rule->cond = cond;
3822 rule->be.name = strdup(args[1]);
3823 LIST_INIT(&rule->list);
3824 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3825 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003826 else if (strcmp(args[0], "use-server") == 0) {
3827 struct server_rule *rule;
3828
3829 if (curproxy == &defproxy) {
3830 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3831 err_code |= ERR_ALERT | ERR_FATAL;
3832 goto out;
3833 }
3834
3835 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3836 err_code |= ERR_WARN;
3837
3838 if (*(args[1]) == 0) {
3839 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3840 err_code |= ERR_ALERT | ERR_FATAL;
3841 goto out;
3842 }
3843
3844 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3845 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3846 file, linenum, args[0]);
3847 err_code |= ERR_ALERT | ERR_FATAL;
3848 goto out;
3849 }
3850
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003851 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3852 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3853 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003854 err_code |= ERR_ALERT | ERR_FATAL;
3855 goto out;
3856 }
3857
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003858 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003859
3860 rule = (struct server_rule *)calloc(1, sizeof(*rule));
3861 rule->cond = cond;
3862 rule->srv.name = strdup(args[1]);
3863 LIST_INIT(&rule->list);
3864 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3865 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3866 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003867 else if ((!strcmp(args[0], "force-persist")) ||
3868 (!strcmp(args[0], "ignore-persist"))) {
3869 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003870
3871 if (curproxy == &defproxy) {
3872 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3873 err_code |= ERR_ALERT | ERR_FATAL;
3874 goto out;
3875 }
3876
3877 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3878 err_code |= ERR_WARN;
3879
Willy Tarreauef6494c2010-01-28 17:12:36 +01003880 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003881 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3882 file, linenum, args[0]);
3883 err_code |= ERR_ALERT | ERR_FATAL;
3884 goto out;
3885 }
3886
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003887 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3888 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3889 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003890 err_code |= ERR_ALERT | ERR_FATAL;
3891 goto out;
3892 }
3893
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003894 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3895 * where force-persist is applied.
3896 */
3897 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003898
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003899 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003900 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003901 if (!strcmp(args[0], "force-persist")) {
3902 rule->type = PERSIST_TYPE_FORCE;
3903 } else {
3904 rule->type = PERSIST_TYPE_IGNORE;
3905 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003906 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003907 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003908 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003909 else if (!strcmp(args[0], "stick-table")) {
3910 int myidx = 1;
Willy Tarreaue45288c2015-05-26 10:49:46 +02003911 struct proxy *other;
3912
Willy Tarreaue2dc1fa2015-05-26 12:08:07 +02003913 other = proxy_tbl_by_name(curproxy->id);
Willy Tarreaue45288c2015-05-26 10:49:46 +02003914 if (other) {
3915 Alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
3916 file, linenum, curproxy->id, proxy_type_str(other), other->id, other->conf.file, other->conf.line);
3917 err_code |= ERR_ALERT | ERR_FATAL;
3918 goto out;
3919 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003920
Emeric Brun32da3c42010-09-23 18:39:19 +02003921 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003922 curproxy->table.type = (unsigned int)-1;
3923 while (*args[myidx]) {
3924 const char *err;
3925
3926 if (strcmp(args[myidx], "size") == 0) {
3927 myidx++;
3928 if (!*(args[myidx])) {
3929 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3930 file, linenum, args[myidx-1]);
3931 err_code |= ERR_ALERT | ERR_FATAL;
3932 goto out;
3933 }
3934 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3935 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3936 file, linenum, *err, args[myidx-1]);
3937 err_code |= ERR_ALERT | ERR_FATAL;
3938 goto out;
3939 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003940 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003941 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003942 else if (strcmp(args[myidx], "peers") == 0) {
3943 myidx++;
Godbach50523162013-12-11 19:48:57 +08003944 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003945 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3946 file, linenum, args[myidx-1]);
3947 err_code |= ERR_ALERT | ERR_FATAL;
3948 goto out;
Godbach50523162013-12-11 19:48:57 +08003949 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003950 curproxy->table.peers.name = strdup(args[myidx++]);
3951 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003952 else if (strcmp(args[myidx], "expire") == 0) {
3953 myidx++;
3954 if (!*(args[myidx])) {
3955 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3956 file, linenum, args[myidx-1]);
3957 err_code |= ERR_ALERT | ERR_FATAL;
3958 goto out;
3959 }
3960 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3961 if (err) {
3962 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3963 file, linenum, *err, args[myidx-1]);
3964 err_code |= ERR_ALERT | ERR_FATAL;
3965 goto out;
3966 }
3967 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003968 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003969 }
3970 else if (strcmp(args[myidx], "nopurge") == 0) {
3971 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003972 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003973 }
3974 else if (strcmp(args[myidx], "type") == 0) {
3975 myidx++;
3976 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3977 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3978 file, linenum, args[myidx]);
3979 err_code |= ERR_ALERT | ERR_FATAL;
3980 goto out;
3981 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003982 /* myidx already points to next arg */
3983 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003984 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003985 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003986 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003987
3988 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003989 nw = args[myidx];
3990 while (*nw) {
3991 /* the "store" keyword supports a comma-separated list */
3992 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003993 sa = NULL; /* store arg */
3994 while (*nw && *nw != ',') {
3995 if (*nw == '(') {
3996 *nw = 0;
3997 sa = ++nw;
3998 while (*nw != ')') {
3999 if (!*nw) {
4000 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
4001 file, linenum, args[0], cw);
4002 err_code |= ERR_ALERT | ERR_FATAL;
4003 goto out;
4004 }
4005 nw++;
4006 }
4007 *nw = '\0';
4008 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004009 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02004010 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004011 if (*nw)
4012 *nw++ = '\0';
4013 type = stktable_get_data_type(cw);
4014 if (type < 0) {
4015 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
4016 file, linenum, args[0], cw);
4017 err_code |= ERR_ALERT | ERR_FATAL;
4018 goto out;
4019 }
Willy Tarreauac782882010-06-20 10:41:54 +02004020
4021 err = stktable_alloc_data_type(&curproxy->table, type, sa);
4022 switch (err) {
4023 case PE_NONE: break;
4024 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004025 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
4026 file, linenum, args[0], cw);
4027 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02004028 break;
4029
4030 case PE_ARG_MISSING:
4031 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
4032 file, linenum, args[0], cw);
4033 err_code |= ERR_ALERT | ERR_FATAL;
4034 goto out;
4035
4036 case PE_ARG_NOT_USED:
4037 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
4038 file, linenum, args[0], cw);
4039 err_code |= ERR_ALERT | ERR_FATAL;
4040 goto out;
4041
4042 default:
4043 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
4044 file, linenum, args[0], cw);
4045 err_code |= ERR_ALERT | ERR_FATAL;
4046 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004047 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004048 }
4049 myidx++;
4050 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004051 else {
4052 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
4053 file, linenum, args[myidx]);
4054 err_code |= ERR_ALERT | ERR_FATAL;
4055 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004056 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004057 }
4058
4059 if (!curproxy->table.size) {
4060 Alert("parsing [%s:%d] : stick-table: missing size.\n",
4061 file, linenum);
4062 err_code |= ERR_ALERT | ERR_FATAL;
4063 goto out;
4064 }
4065
4066 if (curproxy->table.type == (unsigned int)-1) {
4067 Alert("parsing [%s:%d] : stick-table: missing type.\n",
4068 file, linenum);
4069 err_code |= ERR_ALERT | ERR_FATAL;
4070 goto out;
4071 }
4072 }
4073 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004074 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02004075 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004076 int myidx = 0;
4077 const char *name = NULL;
4078 int flags;
4079
4080 if (curproxy == &defproxy) {
4081 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4082 err_code |= ERR_ALERT | ERR_FATAL;
4083 goto out;
4084 }
4085
4086 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
4087 err_code |= ERR_WARN;
4088 goto out;
4089 }
4090
4091 myidx++;
4092 if ((strcmp(args[myidx], "store") == 0) ||
4093 (strcmp(args[myidx], "store-request") == 0)) {
4094 myidx++;
4095 flags = STK_IS_STORE;
4096 }
4097 else if (strcmp(args[myidx], "store-response") == 0) {
4098 myidx++;
4099 flags = STK_IS_STORE | STK_ON_RSP;
4100 }
4101 else if (strcmp(args[myidx], "match") == 0) {
4102 myidx++;
4103 flags = STK_IS_MATCH;
4104 }
4105 else if (strcmp(args[myidx], "on") == 0) {
4106 myidx++;
4107 flags = STK_IS_MATCH | STK_IS_STORE;
4108 }
4109 else {
4110 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
4111 err_code |= ERR_ALERT | ERR_FATAL;
4112 goto out;
4113 }
4114
4115 if (*(args[myidx]) == 0) {
4116 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
4117 err_code |= ERR_ALERT | ERR_FATAL;
4118 goto out;
4119 }
4120
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004121 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01004122 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004123 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01004124 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004125 err_code |= ERR_ALERT | ERR_FATAL;
4126 goto out;
4127 }
4128
4129 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01004130 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
4131 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
4132 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004133 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004134 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004135 goto out;
4136 }
4137 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01004138 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
4139 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
4140 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004141 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004142 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004143 goto out;
4144 }
4145 }
4146
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004147 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01004148 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004149
Emeric Brunb982a3d2010-01-04 15:45:53 +01004150 if (strcmp(args[myidx], "table") == 0) {
4151 myidx++;
4152 name = args[myidx++];
4153 }
4154
Willy Tarreauef6494c2010-01-28 17:12:36 +01004155 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004156 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
4157 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
4158 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004159 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004160 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004161 goto out;
4162 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004163 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01004164 else if (*(args[myidx])) {
4165 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
4166 file, linenum, args[0], args[myidx]);
4167 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004168 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01004169 goto out;
4170 }
Emeric Brun97679e72010-09-23 17:56:44 +02004171 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004172 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02004173 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004174 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01004175
Emeric Brunb982a3d2010-01-04 15:45:53 +01004176 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
4177 rule->cond = cond;
4178 rule->expr = expr;
4179 rule->flags = flags;
4180 rule->table.name = name ? strdup(name) : NULL;
4181 LIST_INIT(&rule->list);
4182 if (flags & STK_ON_RSP)
4183 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
4184 else
4185 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
4186 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004187 else if (!strcmp(args[0], "stats")) {
4188 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
4189 curproxy->uri_auth = NULL; /* we must detach from the default config */
4190
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004191 if (!*args[1]) {
4192 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02004193 } else if (!strcmp(args[1], "admin")) {
4194 struct stats_admin_rule *rule;
4195
4196 if (curproxy == &defproxy) {
4197 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
4198 err_code |= ERR_ALERT | ERR_FATAL;
4199 goto out;
4200 }
4201
4202 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4203 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4204 err_code |= ERR_ALERT | ERR_ABORT;
4205 goto out;
4206 }
4207
4208 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4209 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4210 file, linenum, args[0], args[1]);
4211 err_code |= ERR_ALERT | ERR_FATAL;
4212 goto out;
4213 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004214 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4215 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
4216 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02004217 err_code |= ERR_ALERT | ERR_FATAL;
4218 goto out;
4219 }
4220
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004221 err_code |= warnif_cond_conflicts(cond,
4222 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4223 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02004224
4225 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
4226 rule->cond = cond;
4227 LIST_INIT(&rule->list);
4228 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004229 } else if (!strcmp(args[1], "uri")) {
4230 if (*(args[2]) == 0) {
4231 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004232 err_code |= ERR_ALERT | ERR_FATAL;
4233 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004234 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
4235 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004236 err_code |= ERR_ALERT | ERR_ABORT;
4237 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004238 }
4239 } else if (!strcmp(args[1], "realm")) {
4240 if (*(args[2]) == 0) {
4241 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004242 err_code |= ERR_ALERT | ERR_FATAL;
4243 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004244 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
4245 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004246 err_code |= ERR_ALERT | ERR_ABORT;
4247 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004248 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02004249 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004250 unsigned interval;
4251
4252 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
4253 if (err) {
4254 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
4255 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004256 err_code |= ERR_ALERT | ERR_FATAL;
4257 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004258 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
4259 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004260 err_code |= ERR_ALERT | ERR_ABORT;
4261 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004262 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004263 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004264 struct act_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004265
4266 if (curproxy == &defproxy) {
4267 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4268 err_code |= ERR_ALERT | ERR_FATAL;
4269 goto out;
4270 }
4271
4272 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4273 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4274 err_code |= ERR_ALERT | ERR_ABORT;
4275 goto out;
4276 }
4277
Willy Tarreauff011f22011-01-06 17:51:27 +01004278 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004279 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct act_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004280 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
4281 file, linenum, args[0]);
4282 err_code |= ERR_WARN;
4283 }
4284
Willy Tarreauff011f22011-01-06 17:51:27 +01004285 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004286
Willy Tarreauff011f22011-01-06 17:51:27 +01004287 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004288 err_code |= ERR_ALERT | ERR_ABORT;
4289 goto out;
4290 }
4291
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004292 err_code |= warnif_cond_conflicts(rule->cond,
4293 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4294 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01004295 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004296
Willy Tarreaubaaee002006-06-26 02:48:02 +02004297 } else if (!strcmp(args[1], "auth")) {
4298 if (*(args[2]) == 0) {
4299 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004300 err_code |= ERR_ALERT | ERR_FATAL;
4301 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004302 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
4303 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004304 err_code |= ERR_ALERT | ERR_ABORT;
4305 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004306 }
4307 } else if (!strcmp(args[1], "scope")) {
4308 if (*(args[2]) == 0) {
4309 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004310 err_code |= ERR_ALERT | ERR_FATAL;
4311 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004312 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
4313 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004314 err_code |= ERR_ALERT | ERR_ABORT;
4315 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004316 }
4317 } else if (!strcmp(args[1], "enable")) {
4318 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4319 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004320 err_code |= ERR_ALERT | ERR_ABORT;
4321 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004322 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004323 } else if (!strcmp(args[1], "hide-version")) {
4324 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
4325 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004326 err_code |= ERR_ALERT | ERR_ABORT;
4327 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004328 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01004329 } else if (!strcmp(args[1], "show-legends")) {
4330 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
4331 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4332 err_code |= ERR_ALERT | ERR_ABORT;
4333 goto out;
4334 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004335 } else if (!strcmp(args[1], "show-node")) {
4336
4337 if (*args[2]) {
4338 int i;
4339 char c;
4340
4341 for (i=0; args[2][i]; i++) {
4342 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01004343 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
4344 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004345 break;
4346 }
4347
4348 if (!i || args[2][i]) {
4349 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
4350 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
4351 file, linenum, args[0], args[1]);
4352 err_code |= ERR_ALERT | ERR_FATAL;
4353 goto out;
4354 }
4355 }
4356
4357 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
4358 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4359 err_code |= ERR_ALERT | ERR_ABORT;
4360 goto out;
4361 }
4362 } else if (!strcmp(args[1], "show-desc")) {
4363 char *desc = NULL;
4364
4365 if (*args[2]) {
4366 int i, len=0;
4367 char *d;
4368
Willy Tarreau348acfe2014-04-14 15:00:39 +02004369 for (i = 2; *args[i]; i++)
4370 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004371
4372 desc = d = (char *)calloc(1, len);
4373
Willy Tarreau348acfe2014-04-14 15:00:39 +02004374 d += snprintf(d, desc + len - d, "%s", args[2]);
4375 for (i = 3; *args[i]; i++)
4376 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004377 }
4378
4379 if (!*args[2] && !global.desc)
4380 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
4381 file, linenum, args[1]);
4382 else {
4383 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
4384 free(desc);
4385 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4386 err_code |= ERR_ALERT | ERR_ABORT;
4387 goto out;
4388 }
4389 free(desc);
4390 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004391 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004392stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02004393 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 +01004394 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004395 err_code |= ERR_ALERT | ERR_FATAL;
4396 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004397 }
4398 }
4399 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004400 int optnum;
4401
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004402 if (*(args[1]) == '\0') {
4403 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
4404 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004405 err_code |= ERR_ALERT | ERR_FATAL;
4406 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004407 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01004408
4409 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
4410 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004411 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
4412 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4413 file, linenum, cfg_opts[optnum].name);
4414 err_code |= ERR_ALERT | ERR_FATAL;
4415 goto out;
4416 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004417 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4418 goto out;
4419
Willy Tarreau93893792009-07-23 13:19:11 +02004420 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
4421 err_code |= ERR_WARN;
4422 goto out;
4423 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004424
Willy Tarreau3842f002009-06-14 11:39:52 +02004425 curproxy->no_options &= ~cfg_opts[optnum].val;
4426 curproxy->options &= ~cfg_opts[optnum].val;
4427
4428 switch (kwm) {
4429 case KWM_STD:
4430 curproxy->options |= cfg_opts[optnum].val;
4431 break;
4432 case KWM_NO:
4433 curproxy->no_options |= cfg_opts[optnum].val;
4434 break;
4435 case KWM_DEF: /* already cleared */
4436 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004437 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004438
Willy Tarreau93893792009-07-23 13:19:11 +02004439 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004440 }
4441 }
4442
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004443 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
4444 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004445 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
4446 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4447 file, linenum, cfg_opts2[optnum].name);
4448 err_code |= ERR_ALERT | ERR_FATAL;
4449 goto out;
4450 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004451 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4452 goto out;
Willy Tarreau93893792009-07-23 13:19:11 +02004453 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4454 err_code |= ERR_WARN;
4455 goto out;
4456 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004457
Willy Tarreau3842f002009-06-14 11:39:52 +02004458 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4459 curproxy->options2 &= ~cfg_opts2[optnum].val;
4460
4461 switch (kwm) {
4462 case KWM_STD:
4463 curproxy->options2 |= cfg_opts2[optnum].val;
4464 break;
4465 case KWM_NO:
4466 curproxy->no_options2 |= cfg_opts2[optnum].val;
4467 break;
4468 case KWM_DEF: /* already cleared */
4469 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004470 }
Willy Tarreau93893792009-07-23 13:19:11 +02004471 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004472 }
4473 }
4474
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004475 /* HTTP options override each other. They can be cancelled using
4476 * "no option xxx" which only switches to default mode if the mode
4477 * was this one (useful for cancelling options set in defaults
4478 * sections).
4479 */
4480 if (strcmp(args[1], "httpclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004481 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4482 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004483 if (kwm == KWM_STD) {
4484 curproxy->options &= ~PR_O_HTTP_MODE;
4485 curproxy->options |= PR_O_HTTP_PCL;
4486 goto out;
4487 }
4488 else if (kwm == KWM_NO) {
4489 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4490 curproxy->options &= ~PR_O_HTTP_MODE;
4491 goto out;
4492 }
4493 }
4494 else if (strcmp(args[1], "forceclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004495 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4496 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004497 if (kwm == KWM_STD) {
4498 curproxy->options &= ~PR_O_HTTP_MODE;
4499 curproxy->options |= PR_O_HTTP_FCL;
4500 goto out;
4501 }
4502 else if (kwm == KWM_NO) {
4503 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4504 curproxy->options &= ~PR_O_HTTP_MODE;
4505 goto out;
4506 }
4507 }
4508 else if (strcmp(args[1], "http-server-close") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004509 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4510 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004511 if (kwm == KWM_STD) {
4512 curproxy->options &= ~PR_O_HTTP_MODE;
4513 curproxy->options |= PR_O_HTTP_SCL;
4514 goto out;
4515 }
4516 else if (kwm == KWM_NO) {
4517 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4518 curproxy->options &= ~PR_O_HTTP_MODE;
4519 goto out;
4520 }
4521 }
4522 else if (strcmp(args[1], "http-keep-alive") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004523 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4524 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004525 if (kwm == KWM_STD) {
4526 curproxy->options &= ~PR_O_HTTP_MODE;
4527 curproxy->options |= PR_O_HTTP_KAL;
4528 goto out;
4529 }
4530 else if (kwm == KWM_NO) {
4531 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4532 curproxy->options &= ~PR_O_HTTP_MODE;
4533 goto out;
4534 }
4535 }
4536 else if (strcmp(args[1], "http-tunnel") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004537 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4538 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004539 if (kwm == KWM_STD) {
4540 curproxy->options &= ~PR_O_HTTP_MODE;
4541 curproxy->options |= PR_O_HTTP_TUN;
4542 goto out;
4543 }
4544 else if (kwm == KWM_NO) {
4545 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4546 curproxy->options &= ~PR_O_HTTP_MODE;
4547 goto out;
4548 }
4549 }
4550
Joseph Lynch726ab712015-05-11 23:25:34 -07004551 /* Redispatch can take an integer argument that control when the
4552 * resispatch occurs. All values are relative to the retries option.
4553 * This can be cancelled using "no option xxx".
4554 */
4555 if (strcmp(args[1], "redispatch") == 0) {
4556 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
4557 err_code |= ERR_WARN;
4558 goto out;
4559 }
4560
4561 curproxy->no_options &= ~PR_O_REDISP;
4562 curproxy->options &= ~PR_O_REDISP;
4563
4564 switch (kwm) {
4565 case KWM_STD:
4566 curproxy->options |= PR_O_REDISP;
4567 curproxy->redispatch_after = -1;
4568 if(*args[2]) {
4569 curproxy->redispatch_after = atol(args[2]);
4570 }
4571 break;
4572 case KWM_NO:
4573 curproxy->no_options |= PR_O_REDISP;
4574 curproxy->redispatch_after = 0;
4575 break;
4576 case KWM_DEF: /* already cleared */
4577 break;
4578 }
4579 goto out;
4580 }
4581
Willy Tarreau3842f002009-06-14 11:39:52 +02004582 if (kwm != KWM_STD) {
4583 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004584 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004585 err_code |= ERR_ALERT | ERR_FATAL;
4586 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004587 }
4588
Emeric Brun3a058f32009-06-30 18:26:00 +02004589 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004590 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004591 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004592 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004593 if (*(args[2]) != '\0') {
4594 if (!strcmp(args[2], "clf")) {
4595 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004596 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004597 } else {
William Lallemand77063bc2015-05-28 18:02:48 +02004598 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004599 err_code |= ERR_ALERT | ERR_FATAL;
4600 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004601 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004602 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
4603 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004604 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004605 if (curproxy->conf.logformat_string != default_http_log_format &&
4606 curproxy->conf.logformat_string != default_tcp_log_format &&
4607 curproxy->conf.logformat_string != clf_http_log_format)
4608 free(curproxy->conf.logformat_string);
4609 curproxy->conf.logformat_string = logformat;
4610
4611 free(curproxy->conf.lfs_file);
4612 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4613 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004614 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004615 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004616 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004617 if (curproxy->conf.logformat_string != default_http_log_format &&
4618 curproxy->conf.logformat_string != default_tcp_log_format &&
4619 curproxy->conf.logformat_string != clf_http_log_format)
4620 free(curproxy->conf.logformat_string);
4621 curproxy->conf.logformat_string = default_tcp_log_format;
4622
4623 free(curproxy->conf.lfs_file);
4624 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4625 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemanddf1425a2015-04-28 20:17:49 +02004626
4627 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4628 goto out;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004629 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004630 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004631 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004632 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004633 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004634
William Lallemanddf1425a2015-04-28 20:17:49 +02004635 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4636 goto out;
4637
Willy Tarreau13943ab2006-12-31 00:24:10 +01004638 if (curproxy->cap & PR_CAP_FE)
4639 curproxy->options |= PR_O_TCP_CLI_KA;
4640 if (curproxy->cap & PR_CAP_BE)
4641 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004642 }
4643 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004644 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004645 err_code |= ERR_WARN;
4646
Willy Tarreaubaaee002006-06-26 02:48:02 +02004647 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004648 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004649 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004650 curproxy->options2 &= ~PR_O2_CHK_ANY;
4651 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004652 if (!*args[2]) { /* no argument */
4653 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4654 curproxy->check_len = strlen(DEF_CHECK_REQ);
4655 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004656 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004657 curproxy->check_req = (char *)malloc(reqlen);
4658 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004659 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004660 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004661 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004662 if (*args[4])
4663 reqlen += strlen(args[4]);
4664 else
4665 reqlen += strlen("HTTP/1.0");
4666
4667 curproxy->check_req = (char *)malloc(reqlen);
4668 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004669 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004670 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004671 if (alertif_too_many_args_idx(3, 1, file, linenum, args, &err_code))
4672 goto out;
Willy Tarreauf3c69202006-07-09 16:42:34 +02004673 }
4674 else if (!strcmp(args[1], "ssl-hello-chk")) {
4675 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004676 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004677 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004678
Willy Tarreaua534fea2008-08-03 12:19:50 +02004679 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004680 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004681 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004682 curproxy->options2 |= PR_O2_SSL3_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004683
4684 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4685 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004686 }
Willy Tarreau23677902007-05-08 23:50:35 +02004687 else if (!strcmp(args[1], "smtpchk")) {
4688 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004689 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004690 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004691 curproxy->options2 &= ~PR_O2_CHK_ANY;
4692 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004693
4694 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4695 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4696 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4697 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4698 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4699 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
4700 curproxy->check_req = (char *)malloc(reqlen);
4701 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4702 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4703 } else {
4704 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4705 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4706 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4707 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4708 }
4709 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004710 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4711 goto out;
Willy Tarreau23677902007-05-08 23:50:35 +02004712 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004713 else if (!strcmp(args[1], "pgsql-check")) {
4714 /* use PostgreSQL request to check servers' health */
4715 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4716 err_code |= ERR_WARN;
4717
4718 free(curproxy->check_req);
4719 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004720 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004721 curproxy->options2 |= PR_O2_PGSQL_CHK;
4722
4723 if (*(args[2])) {
4724 int cur_arg = 2;
4725
4726 while (*(args[cur_arg])) {
4727 if (strcmp(args[cur_arg], "user") == 0) {
4728 char * packet;
4729 uint32_t packet_len;
4730 uint32_t pv;
4731
4732 /* suboption header - needs additional argument for it */
4733 if (*(args[cur_arg+1]) == 0) {
4734 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4735 file, linenum, args[0], args[1], args[cur_arg]);
4736 err_code |= ERR_ALERT | ERR_FATAL;
4737 goto out;
4738 }
4739
4740 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4741 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4742 pv = htonl(0x30000); /* protocol version 3.0 */
4743
4744 packet = (char*) calloc(1, packet_len);
4745
4746 memcpy(packet + 4, &pv, 4);
4747
4748 /* copy "user" */
4749 memcpy(packet + 8, "user", 4);
4750
4751 /* copy username */
4752 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4753
4754 free(curproxy->check_req);
4755 curproxy->check_req = packet;
4756 curproxy->check_len = packet_len;
4757
4758 packet_len = htonl(packet_len);
4759 memcpy(packet, &packet_len, 4);
4760 cur_arg += 2;
4761 } else {
4762 /* unknown suboption - catchall */
4763 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4764 file, linenum, args[0], args[1]);
4765 err_code |= ERR_ALERT | ERR_FATAL;
4766 goto out;
4767 }
4768 } /* end while loop */
4769 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004770 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4771 goto out;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004772 }
4773
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004774 else if (!strcmp(args[1], "redis-check")) {
4775 /* use REDIS PING request to check servers' health */
4776 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4777 err_code |= ERR_WARN;
4778
4779 free(curproxy->check_req);
4780 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004781 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004782 curproxy->options2 |= PR_O2_REDIS_CHK;
4783
4784 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
4785 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4786 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004787
4788 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4789 goto out;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004790 }
4791
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004792 else if (!strcmp(args[1], "mysql-check")) {
4793 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004794 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4795 err_code |= ERR_WARN;
4796
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004797 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004798 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004799 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004800 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004801
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004802 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004803 * const char mysql40_client_auth_pkt[] = {
4804 * "\x0e\x00\x00" // packet length
4805 * "\x01" // packet number
4806 * "\x00\x00" // client capabilities
4807 * "\x00\x00\x01" // max packet
4808 * "haproxy\x00" // username (null terminated string)
4809 * "\x00" // filler (always 0x00)
4810 * "\x01\x00\x00" // packet length
4811 * "\x00" // packet number
4812 * "\x01" // COM_QUIT command
4813 * };
4814 */
4815
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004816 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4817 * const char mysql41_client_auth_pkt[] = {
4818 * "\x0e\x00\x00\" // packet length
4819 * "\x01" // packet number
4820 * "\x00\x00\x00\x00" // client capabilities
4821 * "\x00\x00\x00\x01" // max packet
4822 * "\x21" // character set (UTF-8)
4823 * char[23] // All zeroes
4824 * "haproxy\x00" // username (null terminated string)
4825 * "\x00" // filler (always 0x00)
4826 * "\x01\x00\x00" // packet length
4827 * "\x00" // packet number
4828 * "\x01" // COM_QUIT command
4829 * };
4830 */
4831
4832
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004833 if (*(args[2])) {
4834 int cur_arg = 2;
4835
4836 while (*(args[cur_arg])) {
4837 if (strcmp(args[cur_arg], "user") == 0) {
4838 char *mysqluser;
4839 int packetlen, reqlen, userlen;
4840
4841 /* suboption header - needs additional argument for it */
4842 if (*(args[cur_arg+1]) == 0) {
4843 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4844 file, linenum, args[0], args[1], args[cur_arg]);
4845 err_code |= ERR_ALERT | ERR_FATAL;
4846 goto out;
4847 }
4848 mysqluser = args[cur_arg + 1];
4849 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004850
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004851 if (*(args[cur_arg+2])) {
4852 if (!strcmp(args[cur_arg+2], "post-41")) {
4853 packetlen = userlen + 7 + 27;
4854 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004855
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004856 free(curproxy->check_req);
4857 curproxy->check_req = (char *)calloc(1, reqlen);
4858 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004859
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004860 snprintf(curproxy->check_req, 4, "%c%c%c",
4861 ((unsigned char) packetlen & 0xff),
4862 ((unsigned char) (packetlen >> 8) & 0xff),
4863 ((unsigned char) (packetlen >> 16) & 0xff));
4864
4865 curproxy->check_req[3] = 1;
4866 curproxy->check_req[5] = 130;
4867 curproxy->check_req[11] = 1;
4868 curproxy->check_req[12] = 33;
4869 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4870 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4871 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4872 cur_arg += 3;
4873 } else {
4874 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4875 err_code |= ERR_ALERT | ERR_FATAL;
4876 goto out;
4877 }
4878 } else {
4879 packetlen = userlen + 7;
4880 reqlen = packetlen + 9;
4881
4882 free(curproxy->check_req);
4883 curproxy->check_req = (char *)calloc(1, reqlen);
4884 curproxy->check_len = reqlen;
4885
4886 snprintf(curproxy->check_req, 4, "%c%c%c",
4887 ((unsigned char) packetlen & 0xff),
4888 ((unsigned char) (packetlen >> 8) & 0xff),
4889 ((unsigned char) (packetlen >> 16) & 0xff));
4890
4891 curproxy->check_req[3] = 1;
4892 curproxy->check_req[5] = 128;
4893 curproxy->check_req[8] = 1;
4894 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4895 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4896 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4897 cur_arg += 2;
4898 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004899 } else {
4900 /* unknown suboption - catchall */
4901 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4902 file, linenum, args[0], args[1]);
4903 err_code |= ERR_ALERT | ERR_FATAL;
4904 goto out;
4905 }
4906 } /* end while loop */
4907 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004908 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004909 else if (!strcmp(args[1], "ldap-check")) {
4910 /* use LDAP request to check servers' health */
4911 free(curproxy->check_req);
4912 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004913 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004914 curproxy->options2 |= PR_O2_LDAP_CHK;
4915
4916 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
4917 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
4918 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004919 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4920 goto out;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004921 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004922 else if (!strcmp(args[1], "tcp-check")) {
4923 /* use raw TCPCHK send/expect to check servers' health */
4924 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4925 err_code |= ERR_WARN;
4926
4927 free(curproxy->check_req);
4928 curproxy->check_req = NULL;
4929 curproxy->options2 &= ~PR_O2_CHK_ANY;
4930 curproxy->options2 |= PR_O2_TCPCHK_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004931 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4932 goto out;
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004933 }
Simon Horman98637e52014-06-20 12:30:16 +09004934 else if (!strcmp(args[1], "external-check")) {
4935 /* excute an external command to check servers' health */
4936 free(curproxy->check_req);
4937 curproxy->check_req = NULL;
4938 curproxy->options2 &= ~PR_O2_CHK_ANY;
4939 curproxy->options2 |= PR_O2_EXT_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004940 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4941 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09004942 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004943 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004944 int cur_arg;
4945
4946 /* insert x-forwarded-for field, but not for the IP address listed as an except.
4947 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004948 */
Ross Westaf72a1d2008-08-03 10:51:45 +02004949
Willy Tarreau87cf5142011-08-19 22:57:24 +02004950 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02004951
4952 free(curproxy->fwdfor_hdr_name);
4953 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
4954 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
4955
4956 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
4957 cur_arg = 2;
4958 while (*(args[cur_arg])) {
4959 if (!strcmp(args[cur_arg], "except")) {
4960 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004961 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004962 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] 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;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004966 }
4967 /* flush useless bits */
4968 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02004969 cur_arg += 2;
4970 } else if (!strcmp(args[cur_arg], "header")) {
4971 /* suboption header - needs additional argument for it */
4972 if (*(args[cur_arg+1]) == 0) {
4973 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4974 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004975 err_code |= ERR_ALERT | ERR_FATAL;
4976 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02004977 }
4978 free(curproxy->fwdfor_hdr_name);
4979 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
4980 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
4981 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02004982 } else if (!strcmp(args[cur_arg], "if-none")) {
4983 curproxy->options &= ~PR_O_FF_ALWAYS;
4984 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004985 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02004986 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02004987 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02004988 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004989 err_code |= ERR_ALERT | ERR_FATAL;
4990 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004991 }
Ross Westaf72a1d2008-08-03 10:51:45 +02004992 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004993 }
Maik Broemme2850cb42009-04-17 18:53:21 +02004994 else if (!strcmp(args[1], "originalto")) {
4995 int cur_arg;
4996
4997 /* insert x-original-to field, but not for the IP address listed as an except.
4998 * set default options (ie: bitfield, header name, etc)
4999 */
5000
5001 curproxy->options |= PR_O_ORGTO;
5002
5003 free(curproxy->orgto_hdr_name);
5004 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
5005 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
5006
Willy Tarreau87cf5142011-08-19 22:57:24 +02005007 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02005008 cur_arg = 2;
5009 while (*(args[cur_arg])) {
5010 if (!strcmp(args[cur_arg], "except")) {
5011 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005012 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 +02005013 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] 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 /* flush useless bits */
5019 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
5020 cur_arg += 2;
5021 } else if (!strcmp(args[cur_arg], "header")) {
5022 /* suboption header - needs additional argument for it */
5023 if (*(args[cur_arg+1]) == 0) {
5024 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5025 file, linenum, args[0], args[1], args[cur_arg]);
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 free(curproxy->orgto_hdr_name);
5030 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
5031 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
5032 cur_arg += 2;
5033 } else {
5034 /* unknown suboption - catchall */
5035 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
5036 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005037 err_code |= ERR_ALERT | ERR_FATAL;
5038 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005039 }
5040 } /* end while loop */
5041 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005042 else {
5043 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005044 err_code |= ERR_ALERT | ERR_FATAL;
5045 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005046 }
Willy Tarreau93893792009-07-23 13:19:11 +02005047 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005048 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005049 else if (!strcmp(args[0], "default_backend")) {
5050 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005051 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005052
5053 if (*(args[1]) == 0) {
5054 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005055 err_code |= ERR_ALERT | ERR_FATAL;
5056 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005057 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005058 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005059 curproxy->defbe.name = strdup(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005060
5061 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5062 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005063 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005064 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01005065 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005066 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005067
Willy Tarreaua3c504c2014-04-28 22:37:32 +02005068 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
5069 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 +01005070 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005071 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005072 /* enable reconnections to dispatch */
5073 curproxy->options |= PR_O_REDISP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005074
5075 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5076 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005077 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005078 else if (!strcmp(args[0], "http-reuse")) {
5079 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5080 err_code |= ERR_WARN;
5081
5082 if (strcmp(args[1], "never") == 0) {
5083 /* enable a graceful server shutdown on an HTTP 404 response */
5084 curproxy->options &= ~PR_O_REUSE_MASK;
5085 curproxy->options |= PR_O_REUSE_NEVR;
5086 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5087 goto out;
5088 }
Willy Tarreau161d45f2015-08-05 16:02:46 +02005089 else if (strcmp(args[1], "safe") == 0) {
5090 /* enable a graceful server shutdown on an HTTP 404 response */
5091 curproxy->options &= ~PR_O_REUSE_MASK;
5092 curproxy->options |= PR_O_REUSE_SAFE;
5093 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5094 goto out;
5095 }
Willy Tarreau449d74a2015-08-05 17:16:33 +02005096 else if (strcmp(args[1], "aggressive") == 0) {
5097 curproxy->options &= ~PR_O_REUSE_MASK;
5098 curproxy->options |= PR_O_REUSE_AGGR;
5099 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5100 goto out;
5101 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005102 else if (strcmp(args[1], "always") == 0) {
5103 /* enable a graceful server shutdown on an HTTP 404 response */
5104 curproxy->options &= ~PR_O_REUSE_MASK;
5105 curproxy->options |= PR_O_REUSE_ALWS;
5106 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5107 goto out;
5108 }
5109 else {
Willy Tarreau449d74a2015-08-05 17:16:33 +02005110 Alert("parsing [%s:%d] : '%s' only supports 'never', 'safe', 'aggressive', 'always'.\n", file, linenum, args[0]);
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005111 err_code |= ERR_ALERT | ERR_FATAL;
5112 goto out;
5113 }
5114 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005115 else if (!strcmp(args[0], "http-check")) {
5116 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005117 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01005118
5119 if (strcmp(args[1], "disable-on-404") == 0) {
5120 /* enable a graceful server shutdown on an HTTP 404 response */
5121 curproxy->options |= PR_O_DISABLE404;
William Lallemanddf1425a2015-04-28 20:17:49 +02005122 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5123 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005124 }
Willy Tarreauef781042010-01-27 11:53:01 +01005125 else if (strcmp(args[1], "send-state") == 0) {
5126 /* enable emission of the apparent state of a server in HTTP checks */
5127 curproxy->options2 |= PR_O2_CHK_SNDST;
William Lallemanddf1425a2015-04-28 20:17:49 +02005128 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5129 goto out;
Willy Tarreauef781042010-01-27 11:53:01 +01005130 }
Willy Tarreaubd741542010-03-16 18:46:54 +01005131 else if (strcmp(args[1], "expect") == 0) {
5132 const char *ptr_arg;
5133 int cur_arg;
5134
5135 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5136 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5137 err_code |= ERR_ALERT | ERR_FATAL;
5138 goto out;
5139 }
5140
5141 cur_arg = 2;
5142 /* consider exclamation marks, sole or at the beginning of a word */
5143 while (*(ptr_arg = args[cur_arg])) {
5144 while (*ptr_arg == '!') {
5145 curproxy->options2 ^= PR_O2_EXP_INV;
5146 ptr_arg++;
5147 }
5148 if (*ptr_arg)
5149 break;
5150 cur_arg++;
5151 }
5152 /* now ptr_arg points to the beginning of a word past any possible
5153 * exclamation mark, and cur_arg is the argument which holds this word.
5154 */
5155 if (strcmp(ptr_arg, "status") == 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_STS;
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, "string") == 0) {
5167 if (!*(args[cur_arg + 1])) {
5168 Alert("parsing [%s:%d] : '%s %s %s' expects <string> 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_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005174 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005175 curproxy->expect_str = strdup(args[cur_arg + 1]);
5176 }
5177 else if (strcmp(ptr_arg, "rstatus") == 0) {
5178 if (!*(args[cur_arg + 1])) {
5179 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5180 file, linenum, args[0], args[1], ptr_arg);
5181 err_code |= ERR_ALERT | ERR_FATAL;
5182 goto out;
5183 }
5184 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005185 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005186 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005187 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005188 free(curproxy->expect_regex);
5189 curproxy->expect_regex = NULL;
5190 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005191 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005192 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5193 error = NULL;
5194 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5195 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5196 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5197 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005198 err_code |= ERR_ALERT | ERR_FATAL;
5199 goto out;
5200 }
5201 }
5202 else if (strcmp(ptr_arg, "rstring") == 0) {
5203 if (!*(args[cur_arg + 1])) {
5204 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5205 file, linenum, args[0], args[1], ptr_arg);
5206 err_code |= ERR_ALERT | ERR_FATAL;
5207 goto out;
5208 }
5209 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005210 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005211 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005212 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005213 free(curproxy->expect_regex);
5214 curproxy->expect_regex = NULL;
5215 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005216 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005217 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5218 error = NULL;
5219 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5220 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5221 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5222 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005223 err_code |= ERR_ALERT | ERR_FATAL;
5224 goto out;
5225 }
5226 }
5227 else {
5228 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
5229 file, linenum, args[0], args[1], ptr_arg);
5230 err_code |= ERR_ALERT | ERR_FATAL;
5231 goto out;
5232 }
5233 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005234 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005235 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 +02005236 err_code |= ERR_ALERT | ERR_FATAL;
5237 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005238 }
5239 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005240 else if (!strcmp(args[0], "tcp-check")) {
5241 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5242 err_code |= ERR_WARN;
5243
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005244 if (strcmp(args[1], "comment") == 0) {
5245 int cur_arg;
5246 struct tcpcheck_rule *tcpcheck;
5247
5248 cur_arg = 1;
5249 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5250 tcpcheck->action = TCPCHK_ACT_COMMENT;
5251
5252 if (!*args[cur_arg + 1]) {
5253 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5254 file, linenum, args[cur_arg]);
5255 err_code |= ERR_ALERT | ERR_FATAL;
5256 goto out;
5257 }
5258
5259 tcpcheck->comment = strdup(args[cur_arg + 1]);
5260
5261 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
William Lallemanddf1425a2015-04-28 20:17:49 +02005262 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
5263 goto out;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005264 }
5265 else if (strcmp(args[1], "connect") == 0) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005266 const char *ptr_arg;
5267 int cur_arg;
5268 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005269
5270 /* check if first rule is also a 'connect' action */
Willy Tarreau5581c272015-05-13 12:24:53 +02005271 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
5272 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
5273 tcpcheck->action == TCPCHK_ACT_COMMENT) {
5274 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
5275 }
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005276
Willy Tarreau5581c272015-05-13 12:24:53 +02005277 if (&tcpcheck->list != &curproxy->tcpcheck_rules
5278 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
5279 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
5280 file, linenum);
5281 err_code |= ERR_ALERT | ERR_FATAL;
5282 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005283 }
5284
5285 cur_arg = 2;
5286 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5287 tcpcheck->action = TCPCHK_ACT_CONNECT;
5288
5289 /* parsing each parameters to fill up the rule */
5290 while (*(ptr_arg = args[cur_arg])) {
5291 /* tcp port */
5292 if (strcmp(args[cur_arg], "port") == 0) {
5293 if ( (atol(args[cur_arg + 1]) > 65535) ||
5294 (atol(args[cur_arg + 1]) < 1) ){
5295 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
5296 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
5297 err_code |= ERR_ALERT | ERR_FATAL;
5298 goto out;
5299 }
5300 tcpcheck->port = atol(args[cur_arg + 1]);
5301 cur_arg += 2;
5302 }
5303 /* send proxy protocol */
5304 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
5305 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
5306 cur_arg++;
5307 }
5308#ifdef USE_OPENSSL
5309 else if (strcmp(args[cur_arg], "ssl") == 0) {
5310 curproxy->options |= PR_O_TCPCHK_SSL;
5311 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
5312 cur_arg++;
5313 }
5314#endif /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005315 /* comment for this tcpcheck line */
5316 else if (strcmp(args[cur_arg], "comment") == 0) {
5317 if (!*args[cur_arg + 1]) {
5318 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5319 file, linenum, args[cur_arg]);
5320 err_code |= ERR_ALERT | ERR_FATAL;
5321 goto out;
5322 }
5323 tcpcheck->comment = strdup(args[cur_arg + 1]);
5324 cur_arg += 2;
5325 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005326 else {
5327#ifdef USE_OPENSSL
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005328 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 +01005329#else /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005330 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 +01005331#endif /* USE_OPENSSL */
5332 file, linenum, args[0], args[1], args[cur_arg]);
5333 err_code |= ERR_ALERT | ERR_FATAL;
5334 goto out;
5335 }
5336
5337 }
5338
5339 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5340 }
5341 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005342 if (! *(args[2]) ) {
5343 /* SEND string expected */
5344 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
5345 file, linenum, args[0], args[1], args[2]);
5346 err_code |= ERR_ALERT | ERR_FATAL;
5347 goto out;
5348 } else {
5349 struct tcpcheck_rule *tcpcheck;
5350
5351 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5352
5353 tcpcheck->action = TCPCHK_ACT_SEND;
5354 tcpcheck->string_len = strlen(args[2]);
5355 tcpcheck->string = strdup(args[2]);
5356 tcpcheck->expect_regex = NULL;
5357
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005358 /* comment for this tcpcheck line */
5359 if (strcmp(args[3], "comment") == 0) {
5360 if (!*args[4]) {
5361 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5362 file, linenum, args[3]);
5363 err_code |= ERR_ALERT | ERR_FATAL;
5364 goto out;
5365 }
5366 tcpcheck->comment = strdup(args[4]);
5367 }
5368
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005369 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5370 }
5371 }
5372 else if (strcmp(args[1], "send-binary") == 0) {
5373 if (! *(args[2]) ) {
5374 /* SEND binary string expected */
5375 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
5376 file, linenum, args[0], args[1], args[2]);
5377 err_code |= ERR_ALERT | ERR_FATAL;
5378 goto out;
5379 } else {
5380 struct tcpcheck_rule *tcpcheck;
5381 char *err = NULL;
5382
5383 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5384
5385 tcpcheck->action = TCPCHK_ACT_SEND;
5386 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5387 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5388 file, linenum, args[0], args[1], args[2], err);
5389 err_code |= ERR_ALERT | ERR_FATAL;
5390 goto out;
5391 }
5392 tcpcheck->expect_regex = NULL;
5393
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005394 /* comment for this tcpcheck line */
5395 if (strcmp(args[3], "comment") == 0) {
5396 if (!*args[4]) {
5397 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5398 file, linenum, args[3]);
5399 err_code |= ERR_ALERT | ERR_FATAL;
5400 goto out;
5401 }
5402 tcpcheck->comment = strdup(args[4]);
5403 }
5404
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005405 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5406 }
5407 }
5408 else if (strcmp(args[1], "expect") == 0) {
5409 const char *ptr_arg;
5410 int cur_arg;
5411 int inverse = 0;
5412
5413 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5414 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5415 err_code |= ERR_ALERT | ERR_FATAL;
5416 goto out;
5417 }
5418
5419 cur_arg = 2;
5420 /* consider exclamation marks, sole or at the beginning of a word */
5421 while (*(ptr_arg = args[cur_arg])) {
5422 while (*ptr_arg == '!') {
5423 inverse = !inverse;
5424 ptr_arg++;
5425 }
5426 if (*ptr_arg)
5427 break;
5428 cur_arg++;
5429 }
5430 /* now ptr_arg points to the beginning of a word past any possible
5431 * exclamation mark, and cur_arg is the argument which holds this word.
5432 */
5433 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005434 struct tcpcheck_rule *tcpcheck;
5435 char *err = NULL;
5436
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005437 if (!*(args[cur_arg + 1])) {
5438 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
5439 file, linenum, args[0], args[1], ptr_arg);
5440 err_code |= ERR_ALERT | ERR_FATAL;
5441 goto out;
5442 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005443
5444 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5445
5446 tcpcheck->action = TCPCHK_ACT_EXPECT;
5447 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5448 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5449 file, linenum, args[0], args[1], args[2], err);
5450 err_code |= ERR_ALERT | ERR_FATAL;
5451 goto out;
5452 }
5453 tcpcheck->expect_regex = NULL;
5454 tcpcheck->inverse = inverse;
5455
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005456 /* tcpcheck comment */
5457 cur_arg += 2;
5458 if (strcmp(args[cur_arg], "comment") == 0) {
5459 if (!*args[cur_arg + 1]) {
5460 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5461 file, linenum, args[cur_arg + 1]);
5462 err_code |= ERR_ALERT | ERR_FATAL;
5463 goto out;
5464 }
5465 tcpcheck->comment = strdup(args[cur_arg + 1]);
5466 }
5467
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005468 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5469 }
5470 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005471 struct tcpcheck_rule *tcpcheck;
5472
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005473 if (!*(args[cur_arg + 1])) {
5474 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5475 file, linenum, args[0], args[1], ptr_arg);
5476 err_code |= ERR_ALERT | ERR_FATAL;
5477 goto out;
5478 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005479
5480 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5481
5482 tcpcheck->action = TCPCHK_ACT_EXPECT;
5483 tcpcheck->string_len = strlen(args[cur_arg + 1]);
5484 tcpcheck->string = strdup(args[cur_arg + 1]);
5485 tcpcheck->expect_regex = NULL;
5486 tcpcheck->inverse = inverse;
5487
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005488 /* tcpcheck comment */
5489 cur_arg += 2;
5490 if (strcmp(args[cur_arg], "comment") == 0) {
5491 if (!*args[cur_arg + 1]) {
5492 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5493 file, linenum, args[cur_arg + 1]);
5494 err_code |= ERR_ALERT | ERR_FATAL;
5495 goto out;
5496 }
5497 tcpcheck->comment = strdup(args[cur_arg + 1]);
5498 }
5499
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005500 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5501 }
5502 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005503 struct tcpcheck_rule *tcpcheck;
5504
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005505 if (!*(args[cur_arg + 1])) {
5506 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5507 file, linenum, args[0], args[1], ptr_arg);
5508 err_code |= ERR_ALERT | ERR_FATAL;
5509 goto out;
5510 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005511
5512 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5513
5514 tcpcheck->action = TCPCHK_ACT_EXPECT;
5515 tcpcheck->string_len = 0;
5516 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005517 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
5518 error = NULL;
5519 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
5520 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5521 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5522 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005523 err_code |= ERR_ALERT | ERR_FATAL;
5524 goto out;
5525 }
5526 tcpcheck->inverse = inverse;
5527
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005528 /* tcpcheck comment */
5529 cur_arg += 2;
5530 if (strcmp(args[cur_arg], "comment") == 0) {
5531 if (!*args[cur_arg + 1]) {
5532 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5533 file, linenum, args[cur_arg + 1]);
5534 err_code |= ERR_ALERT | ERR_FATAL;
5535 goto out;
5536 }
5537 tcpcheck->comment = strdup(args[cur_arg + 1]);
5538 }
5539
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005540 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5541 }
5542 else {
5543 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
5544 file, linenum, args[0], args[1], ptr_arg);
5545 err_code |= ERR_ALERT | ERR_FATAL;
5546 goto out;
5547 }
5548 }
5549 else {
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005550 Alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005551 err_code |= ERR_ALERT | ERR_FATAL;
5552 goto out;
5553 }
5554 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01005555 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02005556 if (curproxy == &defproxy) {
5557 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005558 err_code |= ERR_ALERT | ERR_FATAL;
5559 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02005560 }
5561
Willy Tarreaub80c2302007-11-30 20:51:32 +01005562 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005563 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005564
5565 if (strcmp(args[1], "fail") == 0) {
5566 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01005567 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01005568 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
5569 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005570 err_code |= ERR_ALERT | ERR_FATAL;
5571 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005572 }
5573
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005574 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
5575 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
5576 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005577 err_code |= ERR_ALERT | ERR_FATAL;
5578 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005579 }
5580 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
5581 }
5582 else {
5583 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005584 err_code |= ERR_ALERT | ERR_FATAL;
5585 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005586 }
5587 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005588#ifdef TPROXY
5589 else if (!strcmp(args[0], "transparent")) {
5590 /* enable transparent proxy connections */
5591 curproxy->options |= PR_O_TRANSP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005592 if (alertif_too_many_args(0, file, linenum, args, &err_code))
5593 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005594 }
5595#endif
5596 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005597 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005598 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005599
Willy Tarreaubaaee002006-06-26 02:48:02 +02005600 if (*(args[1]) == 0) {
5601 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005602 err_code |= ERR_ALERT | ERR_FATAL;
5603 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005604 }
5605 curproxy->maxconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005606 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5607 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005608 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005609 else if (!strcmp(args[0], "backlog")) { /* backlog */
5610 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005611 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005612
5613 if (*(args[1]) == 0) {
5614 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005615 err_code |= ERR_ALERT | ERR_FATAL;
5616 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005617 }
5618 curproxy->backlog = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005619 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5620 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005621 }
Willy Tarreau86034312006-12-29 00:10:33 +01005622 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005623 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005624 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005625
Willy Tarreau86034312006-12-29 00:10:33 +01005626 if (*(args[1]) == 0) {
5627 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005628 err_code |= ERR_ALERT | ERR_FATAL;
5629 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005630 }
5631 curproxy->fullconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005632 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5633 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005634 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005635 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
5636 if (*(args[1]) == 0) {
5637 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005638 err_code |= ERR_ALERT | ERR_FATAL;
5639 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005640 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005641 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
5642 if (err) {
5643 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
5644 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02005645 err_code |= ERR_ALERT | ERR_FATAL;
5646 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005647 }
5648 curproxy->grace = val;
William Lallemanddf1425a2015-04-28 20:17:49 +02005649 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5650 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005651 }
5652 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01005653 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005654 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005655 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005656
Willy Tarreaubaaee002006-06-26 02:48:02 +02005657 if (curproxy == &defproxy) {
5658 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005659 err_code |= ERR_ALERT | ERR_FATAL;
5660 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005661 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005662 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005663 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005664
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02005665 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005666 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005667 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005668 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005669 goto out;
5670 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005671
5672 proto = protocol_by_family(sk->ss_family);
5673 if (!proto || !proto->connect) {
5674 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5675 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005676 err_code |= ERR_ALERT | ERR_FATAL;
5677 goto out;
5678 }
5679
5680 if (port1 != port2) {
5681 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5682 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005683 err_code |= ERR_ALERT | ERR_FATAL;
5684 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005685 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005686
5687 if (!port1) {
5688 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5689 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005690 err_code |= ERR_ALERT | ERR_FATAL;
5691 goto out;
5692 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005693
William Lallemanddf1425a2015-04-28 20:17:49 +02005694 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5695 goto out;
5696
Willy Tarreaud5191e72010-02-09 20:50:45 +01005697 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005698 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005699 }
5700 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005701 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005702 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005703
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005704 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5705 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005706 err_code |= ERR_ALERT | ERR_FATAL;
5707 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005708 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005709 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005710 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005711 /**
5712 * The syntax for hash-type config element is
5713 * hash-type {map-based|consistent} [[<algo>] avalanche]
5714 *
5715 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5716 */
5717 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005718
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005719 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5720 err_code |= ERR_WARN;
5721
5722 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005723 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5724 }
5725 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005726 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5727 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005728 else if (strcmp(args[1], "avalanche") == 0) {
5729 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]);
5730 err_code |= ERR_ALERT | ERR_FATAL;
5731 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005732 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005733 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005734 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005735 err_code |= ERR_ALERT | ERR_FATAL;
5736 goto out;
5737 }
Bhaskar98634f02013-10-29 23:30:51 -04005738
5739 /* set the hash function to use */
5740 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005741 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005742 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005743
5744 /* if consistent with no argument, then avalanche modifier is also applied */
5745 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5746 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005747 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005748 /* set the hash function */
5749 if (!strcmp(args[2], "sdbm")) {
5750 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5751 }
5752 else if (!strcmp(args[2], "djb2")) {
5753 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005754 }
5755 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005756 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005757 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005758 else if (!strcmp(args[2], "crc32")) {
5759 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5760 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005761 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005762 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 -05005763 err_code |= ERR_ALERT | ERR_FATAL;
5764 goto out;
5765 }
5766
5767 /* set the hash modifier */
5768 if (!strcmp(args[3], "avalanche")) {
5769 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5770 }
5771 else if (*args[3]) {
5772 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5773 err_code |= ERR_ALERT | ERR_FATAL;
5774 goto out;
5775 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005776 }
William Lallemanda73203e2012-03-12 12:48:57 +01005777 }
William Lallemanda73203e2012-03-12 12:48:57 +01005778 else if (strcmp(args[0], "unique-id-format") == 0) {
5779 if (!*(args[1])) {
5780 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5781 err_code |= ERR_ALERT | ERR_FATAL;
5782 goto out;
5783 }
William Lallemand3203ff42012-11-11 17:30:56 +01005784 if (*(args[2])) {
5785 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5786 err_code |= ERR_ALERT | ERR_FATAL;
5787 goto out;
5788 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005789 free(curproxy->conf.uniqueid_format_string);
5790 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005791
Willy Tarreau62a61232013-04-12 18:13:46 +02005792 free(curproxy->conf.uif_file);
5793 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5794 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005795 }
William Lallemanda73203e2012-03-12 12:48:57 +01005796
5797 else if (strcmp(args[0], "unique-id-header") == 0) {
5798 if (!*(args[1])) {
5799 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5800 err_code |= ERR_ALERT | ERR_FATAL;
5801 goto out;
5802 }
5803 free(curproxy->header_unique_id);
5804 curproxy->header_unique_id = strdup(args[1]);
5805 }
5806
William Lallemand723b73a2012-02-08 16:37:49 +01005807 else if (strcmp(args[0], "log-format") == 0) {
5808 if (!*(args[1])) {
5809 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5810 err_code |= ERR_ALERT | ERR_FATAL;
5811 goto out;
5812 }
William Lallemand3203ff42012-11-11 17:30:56 +01005813 if (*(args[2])) {
5814 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5815 err_code |= ERR_ALERT | ERR_FATAL;
5816 goto out;
5817 }
Willy Tarreau196729e2012-05-31 19:30:26 +02005818
Willy Tarreau62a61232013-04-12 18:13:46 +02005819 if (curproxy->conf.logformat_string != default_http_log_format &&
5820 curproxy->conf.logformat_string != default_tcp_log_format &&
5821 curproxy->conf.logformat_string != clf_http_log_format)
5822 free(curproxy->conf.logformat_string);
5823 curproxy->conf.logformat_string = strdup(args[1]);
5824
5825 free(curproxy->conf.lfs_file);
5826 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5827 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005828
5829 /* get a chance to improve log-format error reporting by
5830 * reporting the correct line-number when possible.
5831 */
5832 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5833 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5834 file, linenum, curproxy->id);
5835 err_code |= ERR_WARN;
5836 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005837 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02005838 else if (!strcmp(args[0], "log-format-sd")) {
5839 if (!*(args[1])) {
5840 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5841 err_code |= ERR_ALERT | ERR_FATAL;
5842 goto out;
5843 }
5844 if (*(args[2])) {
5845 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5846 err_code |= ERR_ALERT | ERR_FATAL;
5847 goto out;
5848 }
5849
5850 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
5851 free(curproxy->conf.logformat_sd_string);
5852 curproxy->conf.logformat_sd_string = strdup(args[1]);
5853
5854 free(curproxy->conf.lfsd_file);
5855 curproxy->conf.lfsd_file = strdup(curproxy->conf.args.file);
5856 curproxy->conf.lfsd_line = curproxy->conf.args.line;
5857
5858 /* get a chance to improve log-format-sd error reporting by
5859 * reporting the correct line-number when possible.
5860 */
5861 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5862 Warning("parsing [%s:%d] : backend '%s' : 'log-format-sd' directive is ignored in backends.\n",
5863 file, linenum, curproxy->id);
5864 err_code |= ERR_WARN;
5865 }
5866 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01005867 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
5868 if (*(args[1]) == 0) {
5869 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
5870 err_code |= ERR_ALERT | ERR_FATAL;
5871 goto out;
5872 }
Dragan Dosen43885c72015-10-01 13:18:13 +02005873 chunk_destroy(&curproxy->log_tag);
5874 chunk_initstr(&curproxy->log_tag, strdup(args[1]));
Willy Tarreau094af4e2015-01-07 15:03:42 +01005875 }
William Lallemand0f99e342011-10-12 17:50:54 +02005876 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
5877 /* delete previous herited or defined syslog servers */
5878 struct logsrv *back;
5879
5880 if (*(args[1]) != 0) {
5881 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
5882 err_code |= ERR_ALERT | ERR_FATAL;
5883 goto out;
5884 }
5885
William Lallemand723b73a2012-02-08 16:37:49 +01005886 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
5887 LIST_DEL(&tmplogsrv->list);
5888 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02005889 }
5890 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005891 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02005892 struct logsrv *logsrv;
5893
Willy Tarreaubaaee002006-06-26 02:48:02 +02005894 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005895 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01005896 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02005897 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01005898 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02005899 LIST_INIT(&node->list);
5900 LIST_ADDQ(&curproxy->logsrvs, &node->list);
5901 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005902 }
5903 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005904 struct sockaddr_storage *sk;
5905 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02005906 int arg = 0;
5907 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02005908
5909 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005910
Willy Tarreau18324f52014-06-27 18:10:07 +02005911 /* just after the address, a length may be specified */
5912 if (strcmp(args[arg+2], "len") == 0) {
5913 len = atoi(args[arg+3]);
5914 if (len < 80 || len > 65535) {
5915 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
5916 file, linenum, args[arg+3]);
5917 err_code |= ERR_ALERT | ERR_FATAL;
5918 goto out;
5919 }
5920 logsrv->maxlen = len;
5921
5922 /* skip these two args */
5923 arg += 2;
5924 }
5925 else
5926 logsrv->maxlen = MAX_SYSLOG_LEN;
5927
5928 if (logsrv->maxlen > global.max_syslog_len) {
5929 global.max_syslog_len = logsrv->maxlen;
Dragan Dosen59cee972015-09-19 22:09:02 +02005930 logheader = realloc(logheader, global.max_syslog_len + 1);
Dragan Dosen1322d092015-09-22 16:05:32 +02005931 logheader_rfc5424 = realloc(logheader_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02005932 logline = realloc(logline, global.max_syslog_len + 1);
Dragan Dosen0b85ece2015-09-25 19:17:44 +02005933 logline_rfc5424 = realloc(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02005934 }
5935
Dragan Dosen1322d092015-09-22 16:05:32 +02005936 /* after the length, a format may be specified */
5937 if (strcmp(args[arg+2], "format") == 0) {
5938 logsrv->format = get_log_format(args[arg+3]);
5939 if (logsrv->format < 0) {
5940 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
5941 err_code |= ERR_ALERT | ERR_FATAL;
5942 goto out;
5943 }
5944
5945 /* skip these two args */
5946 arg += 2;
5947 }
5948
William Lallemanddf1425a2015-04-28 20:17:49 +02005949 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
5950 goto out;
5951
Willy Tarreau18324f52014-06-27 18:10:07 +02005952 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005953 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005954 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005955 err_code |= ERR_ALERT | ERR_FATAL;
5956 goto out;
5957
Willy Tarreaubaaee002006-06-26 02:48:02 +02005958 }
5959
William Lallemand0f99e342011-10-12 17:50:54 +02005960 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02005961 if (*(args[arg+3])) {
5962 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005963 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005964 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005965 err_code |= ERR_ALERT | ERR_FATAL;
5966 goto out;
5967
Willy Tarreaubaaee002006-06-26 02:48:02 +02005968 }
5969 }
5970
William Lallemand0f99e342011-10-12 17:50:54 +02005971 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02005972 if (*(args[arg+4])) {
5973 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01005974 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005975 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02005976 err_code |= ERR_ALERT | ERR_FATAL;
5977 goto out;
5978
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005979 }
5980 }
5981
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02005982 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005983 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005984 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005985 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005986 goto out;
5987 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005988
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005989 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005990
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005991 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005992 if (port1 != port2) {
5993 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5994 file, linenum, args[0], args[1]);
5995 err_code |= ERR_ALERT | ERR_FATAL;
5996 goto out;
5997 }
5998
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005999 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02006000 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006001 }
William Lallemand0f99e342011-10-12 17:50:54 +02006002
6003 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006004 }
6005 else {
6006 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
6007 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02006008 err_code |= ERR_ALERT | ERR_FATAL;
6009 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006010 }
6011 }
6012 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006013 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006014 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01006015 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006016 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006017
Willy Tarreau977b8e42006-12-29 14:19:17 +01006018 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006019 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006020
Willy Tarreaubaaee002006-06-26 02:48:02 +02006021 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006022 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
6023 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02006024 err_code |= ERR_ALERT | ERR_FATAL;
6025 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006026 }
Willy Tarreau368480c2009-03-01 08:27:21 +01006027
6028 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01006029 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6030 free(curproxy->conn_src.iface_name);
6031 curproxy->conn_src.iface_name = NULL;
6032 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01006033
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006034 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006035 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006036 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006037 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006038 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006039 goto out;
6040 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006041
6042 proto = protocol_by_family(sk->ss_family);
6043 if (!proto || !proto->connect) {
6044 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006045 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006046 err_code |= ERR_ALERT | ERR_FATAL;
6047 goto out;
6048 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006049
6050 if (port1 != port2) {
6051 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6052 file, linenum, args[0], args[1]);
6053 err_code |= ERR_ALERT | ERR_FATAL;
6054 goto out;
6055 }
6056
Willy Tarreauef9a3602012-12-08 22:29:20 +01006057 curproxy->conn_src.source_addr = *sk;
6058 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006059
6060 cur_arg = 2;
6061 while (*(args[cur_arg])) {
6062 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau29fbe512015-08-20 19:35:14 +02006063#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006064 if (!*args[cur_arg + 1]) {
6065 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
6066 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006067 err_code |= ERR_ALERT | ERR_FATAL;
6068 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006069 }
6070
6071 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006072 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6073 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006074 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006075 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6076 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02006077 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
6078 char *name, *end;
6079
6080 name = args[cur_arg+1] + 7;
6081 while (isspace(*name))
6082 name++;
6083
6084 end = name;
6085 while (*end && !isspace(*end) && *end != ',' && *end != ')')
6086 end++;
6087
Willy Tarreauef9a3602012-12-08 22:29:20 +01006088 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6089 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
6090 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
6091 curproxy->conn_src.bind_hdr_len = end - name;
6092 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
6093 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
6094 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02006095
6096 /* now look for an occurrence number */
6097 while (isspace(*end))
6098 end++;
6099 if (*end == ',') {
6100 end++;
6101 name = end;
6102 if (*end == '-')
6103 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01006104 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02006105 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01006106 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006107 }
6108
Willy Tarreauef9a3602012-12-08 22:29:20 +01006109 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02006110 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
6111 " occurrences values smaller than %d.\n",
6112 file, linenum, MAX_HDR_HISTORY);
6113 err_code |= ERR_ALERT | ERR_FATAL;
6114 goto out;
6115 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006116 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01006117 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006118
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006119 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006120 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006121 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006122 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006123 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006124 goto out;
6125 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006126
6127 proto = protocol_by_family(sk->ss_family);
6128 if (!proto || !proto->connect) {
6129 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
6130 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006131 err_code |= ERR_ALERT | ERR_FATAL;
6132 goto out;
6133 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006134
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006135 if (port1 != port2) {
6136 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6137 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006138 err_code |= ERR_ALERT | ERR_FATAL;
6139 goto out;
6140 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006141 curproxy->conn_src.tproxy_addr = *sk;
6142 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006143 }
6144 global.last_checks |= LSTCHK_NETADM;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006145#else /* no TPROXY support */
6146 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01006147 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006148 err_code |= ERR_ALERT | ERR_FATAL;
6149 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006150#endif
6151 cur_arg += 2;
6152 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01006153 }
6154
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006155 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
6156#ifdef SO_BINDTODEVICE
6157 if (!*args[cur_arg + 1]) {
6158 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
6159 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006160 err_code |= ERR_ALERT | ERR_FATAL;
6161 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006162 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006163 free(curproxy->conn_src.iface_name);
6164 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
6165 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006166 global.last_checks |= LSTCHK_NETADM;
6167#else
6168 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
6169 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02006170 err_code |= ERR_ALERT | ERR_FATAL;
6171 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01006172#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006173 cur_arg += 2;
6174 continue;
6175 }
6176 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02006177 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006178 err_code |= ERR_ALERT | ERR_FATAL;
6179 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006180 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006181 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006182 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
6183 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
6184 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02006185 err_code |= ERR_ALERT | ERR_FATAL;
6186 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006187 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006188 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006189 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006190 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6191 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006192 err_code |= ERR_ALERT | ERR_FATAL;
6193 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006194 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006195
6196 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006197 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006198 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006199 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006200 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006201 }
6202 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006203 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006204 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006205 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006206 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006207 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006208 }
6209 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006210 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006211 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006212 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006213 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006214 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006215 }
6216 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006217 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006218 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006219 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006220 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006221 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006222 }
6223 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006224 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006225 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006226 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006227 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006228 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006229 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006230 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006231 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006232 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006233 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006234 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006235 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006236 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006237 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006238 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006239 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6240 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006241 err_code |= ERR_ALERT | ERR_FATAL;
6242 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006243 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006244
6245 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006246 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006247 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006248 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006249 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006250 }
6251 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006252 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006253 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006254 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006255 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006256 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006257 }
6258 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006259 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006260 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006261 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006262 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006263 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006264 }
6265 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006266 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006267 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006268 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006269 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006270 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006271 }
6272 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006273 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006274 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006275 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006276 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006277 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006278 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006279 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006280 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006281 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006282 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006283 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006284 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006285 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006286 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006287 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006288
Willy Tarreaubaaee002006-06-26 02:48:02 +02006289 if (curproxy == &defproxy) {
6290 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006291 err_code |= ERR_ALERT | ERR_FATAL;
6292 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006293 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006294 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006295 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006296
Willy Tarreaubaaee002006-06-26 02:48:02 +02006297 if (*(args[1]) == 0) {
6298 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006299 err_code |= ERR_ALERT | ERR_FATAL;
6300 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006301 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006302
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006303 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006304 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6305 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6306 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006307 err_code |= ERR_ALERT | ERR_FATAL;
6308 goto out;
6309 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006310 err_code |= warnif_cond_conflicts(cond,
6311 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6312 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006313 }
6314 else if (*args[2]) {
6315 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6316 file, linenum, args[0], args[2]);
6317 err_code |= ERR_ALERT | ERR_FATAL;
6318 goto out;
6319 }
6320
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006321 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006322 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006323 wl->s = strdup(args[1]);
6324 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02006325 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006326 }
6327 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006328 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006329 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6330 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006331 err_code |= ERR_ALERT | ERR_FATAL;
6332 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006333 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006334
Willy Tarreauade5ec42010-01-28 19:33:49 +01006335 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006336 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006337 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006338 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006339 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006340 }
6341 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006342 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006343 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006344 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006345 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006346 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006347 }
6348 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006349 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006350 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006351 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006352 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006353 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006354 }
6355 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006356 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006357 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6358 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006359 err_code |= ERR_ALERT | ERR_FATAL;
6360 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006361 }
6362
Willy Tarreauade5ec42010-01-28 19:33:49 +01006363 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006364 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006365 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006366 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006367 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006368 }
6369 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006370 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006371 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006372 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006373 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006374 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006375 }
6376 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006377 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006378 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006379 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006380 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006381 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006382 }
6383 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006384 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006385
Willy Tarreaubaaee002006-06-26 02:48:02 +02006386 if (curproxy == &defproxy) {
6387 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006388 err_code |= ERR_ALERT | ERR_FATAL;
6389 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006390 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006391 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006392 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006393
Willy Tarreaubaaee002006-06-26 02:48:02 +02006394 if (*(args[1]) == 0) {
6395 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006396 err_code |= ERR_ALERT | ERR_FATAL;
6397 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006398 }
6399
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006400 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006401 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6402 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6403 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006404 err_code |= ERR_ALERT | ERR_FATAL;
6405 goto out;
6406 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006407 err_code |= warnif_cond_conflicts(cond,
6408 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
6409 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006410 }
6411 else if (*args[2]) {
6412 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6413 file, linenum, args[0], args[2]);
6414 err_code |= ERR_ALERT | ERR_FATAL;
6415 goto out;
6416 }
6417
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006418 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006419 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006420 wl->s = strdup(args[1]);
6421 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006422 }
6423 else if (!strcmp(args[0], "errorloc") ||
6424 !strcmp(args[0], "errorloc302") ||
6425 !strcmp(args[0], "errorloc303")) { /* error location */
6426 int errnum, errlen;
6427 char *err;
6428
Willy Tarreau977b8e42006-12-29 14:19:17 +01006429 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006430 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006431
Willy Tarreaubaaee002006-06-26 02:48:02 +02006432 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006433 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006434 err_code |= ERR_ALERT | ERR_FATAL;
6435 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006436 }
6437
6438 errnum = atol(args[1]);
6439 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006440 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
6441 err = malloc(errlen);
6442 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006443 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006444 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
6445 err = malloc(errlen);
6446 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006447 }
6448
Willy Tarreau0f772532006-12-23 20:51:41 +01006449 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6450 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006451 chunk_destroy(&curproxy->errmsg[rc]);
6452 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01006453 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006454 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006455 }
Willy Tarreau0f772532006-12-23 20:51:41 +01006456
6457 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006458 Warning("parsing [%s:%d] : status code %d not handled by '%s', error relocation will be ignored.\n",
6459 file, linenum, errnum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006460 free(err);
6461 }
6462 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02006463 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
6464 int errnum, errlen, fd;
6465 char *err;
6466 struct stat stat;
6467
6468 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006469 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006470
6471 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006472 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006473 err_code |= ERR_ALERT | ERR_FATAL;
6474 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006475 }
6476
6477 fd = open(args[2], O_RDONLY);
6478 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
6479 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
6480 file, linenum, args[2], args[1]);
6481 if (fd >= 0)
6482 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02006483 err_code |= ERR_ALERT | ERR_FATAL;
6484 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006485 }
6486
Willy Tarreau27a674e2009-08-17 07:23:33 +02006487 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02006488 errlen = stat.st_size;
6489 } else {
6490 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02006491 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02006492 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02006493 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006494 }
6495
6496 err = malloc(errlen); /* malloc() must succeed during parsing */
6497 errnum = read(fd, err, errlen);
6498 if (errnum != errlen) {
6499 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
6500 file, linenum, args[2], args[1]);
6501 close(fd);
6502 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02006503 err_code |= ERR_ALERT | ERR_FATAL;
6504 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006505 }
6506 close(fd);
6507
6508 errnum = atol(args[1]);
6509 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6510 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006511 chunk_destroy(&curproxy->errmsg[rc]);
6512 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02006513 break;
6514 }
6515 }
6516
6517 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006518 Warning("parsing [%s:%d] : status code %d not handled by '%s', error customization will be ignored.\n",
6519 file, linenum, errnum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006520 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006521 free(err);
6522 }
6523 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006524 else if (!strcmp(args[0], "compression")) {
6525 struct comp *comp;
6526 if (curproxy->comp == NULL) {
6527 comp = calloc(1, sizeof(struct comp));
6528 curproxy->comp = comp;
6529 } else {
6530 comp = curproxy->comp;
6531 }
6532
6533 if (!strcmp(args[1], "algo")) {
6534 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01006535 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01006536
William Lallemand82fe75c2012-10-23 10:25:10 +02006537 cur_arg = 2;
6538 if (!*args[cur_arg]) {
6539 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
6540 file, linenum, args[0]);
6541 err_code |= ERR_ALERT | ERR_FATAL;
6542 goto out;
6543 }
6544 while (*(args[cur_arg])) {
6545 if (comp_append_algo(comp, args[cur_arg]) < 0) {
6546 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
6547 file, linenum, args[0], args[cur_arg]);
6548 err_code |= ERR_ALERT | ERR_FATAL;
6549 goto out;
6550 }
William Lallemand552df672012-11-07 13:21:47 +01006551 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
6552 curproxy->comp->algos->end(&ctx);
6553 } else {
6554 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
6555 file, linenum, args[0], args[cur_arg]);
6556 err_code |= ERR_ALERT | ERR_FATAL;
6557 goto out;
6558 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006559 cur_arg ++;
6560 continue;
6561 }
6562 }
Willy Tarreau70737d12012-10-27 00:34:28 +02006563 else if (!strcmp(args[1], "offload")) {
6564 comp->offload = 1;
6565 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006566 else if (!strcmp(args[1], "type")) {
6567 int cur_arg;
6568 cur_arg = 2;
6569 if (!*args[cur_arg]) {
6570 Alert("parsing [%s:%d] : '%s' expects <type>\n",
6571 file, linenum, args[0]);
6572 err_code |= ERR_ALERT | ERR_FATAL;
6573 goto out;
6574 }
6575 while (*(args[cur_arg])) {
6576 comp_append_type(comp, args[cur_arg]);
6577 cur_arg ++;
6578 continue;
6579 }
6580 }
6581 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02006582 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02006583 file, linenum, args[0]);
6584 err_code |= ERR_ALERT | ERR_FATAL;
6585 goto out;
6586 }
6587 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006588 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006589 struct cfg_kw_list *kwl;
6590 int index;
6591
6592 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6593 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6594 if (kwl->kw[index].section != CFG_LISTEN)
6595 continue;
6596 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6597 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006598 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006599 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006600 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006601 err_code |= ERR_ALERT | ERR_FATAL;
6602 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006603 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006604 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006605 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006606 err_code |= ERR_WARN;
6607 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006608 }
Willy Tarreau93893792009-07-23 13:19:11 +02006609 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006610 }
6611 }
6612 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006613
Willy Tarreau6daf3432008-01-22 16:44:08 +01006614 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006615 err_code |= ERR_ALERT | ERR_FATAL;
6616 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006617 }
Willy Tarreau93893792009-07-23 13:19:11 +02006618 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006619 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006620 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006621}
6622
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006623int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006624cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
6625{
6626#ifdef CONFIG_HAP_NS
6627 const char *err;
6628 const char *item = args[0];
6629
6630 if (!strcmp(item, "namespace_list")) {
6631 return 0;
6632 }
6633 else if (!strcmp(item, "namespace")) {
6634 size_t idx = 1;
6635 const char *current;
6636 while (*(current = args[idx++])) {
6637 err = invalid_char(current);
6638 if (err) {
6639 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6640 file, linenum, *err, item, current);
6641 return ERR_ALERT | ERR_FATAL;
6642 }
6643
6644 if (netns_store_lookup(current, strlen(current))) {
6645 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
6646 file, linenum, current);
6647 return ERR_ALERT | ERR_FATAL;
6648 }
6649 if (!netns_store_insert(current)) {
6650 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
6651 file, linenum, current);
6652 return ERR_ALERT | ERR_FATAL;
6653 }
6654 }
6655 }
6656
6657 return 0;
6658#else
6659 Alert("parsing [%s:%d]: namespace support is not compiled in.",
6660 file, linenum);
6661 return ERR_ALERT | ERR_FATAL;
6662#endif
6663}
6664
6665int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006666cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6667{
6668
6669 int err_code = 0;
6670 const char *err;
6671
6672 if (!strcmp(args[0], "userlist")) { /* new userlist */
6673 struct userlist *newul;
6674
6675 if (!*args[1]) {
6676 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6677 file, linenum, args[0]);
6678 err_code |= ERR_ALERT | ERR_FATAL;
6679 goto out;
6680 }
William Lallemand6e62fb62015-04-28 16:55:23 +02006681 if (alertif_too_many_args(1, file, linenum, args, &err_code))
6682 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006683
6684 err = invalid_char(args[1]);
6685 if (err) {
6686 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6687 file, linenum, *err, args[0], args[1]);
6688 err_code |= ERR_ALERT | ERR_FATAL;
6689 goto out;
6690 }
6691
6692 for (newul = userlist; newul; newul = newul->next)
6693 if (!strcmp(newul->name, args[1])) {
6694 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6695 file, linenum, args[1]);
6696 err_code |= ERR_WARN;
6697 goto out;
6698 }
6699
6700 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
6701 if (!newul) {
6702 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6703 err_code |= ERR_ALERT | ERR_ABORT;
6704 goto out;
6705 }
6706
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006707 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006708 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006709 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6710 err_code |= ERR_ALERT | ERR_ABORT;
6711 goto out;
6712 }
6713
6714 newul->next = userlist;
6715 userlist = newul;
6716
6717 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006718 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006719 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006720 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006721
6722 if (!*args[1]) {
6723 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6724 file, linenum, args[0]);
6725 err_code |= ERR_ALERT | ERR_FATAL;
6726 goto out;
6727 }
6728
6729 err = invalid_char(args[1]);
6730 if (err) {
6731 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6732 file, linenum, *err, args[0], args[1]);
6733 err_code |= ERR_ALERT | ERR_FATAL;
6734 goto out;
6735 }
6736
William Lallemand4ac9f542015-05-28 18:03:51 +02006737 if (!userlist)
6738 goto out;
6739
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006740 for (ag = userlist->groups; ag; ag = ag->next)
6741 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006742 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6743 file, linenum, args[1], userlist->name);
6744 err_code |= ERR_ALERT;
6745 goto out;
6746 }
6747
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006748 ag = calloc(1, sizeof(*ag));
6749 if (!ag) {
6750 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6751 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006752 goto out;
6753 }
6754
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006755 ag->name = strdup(args[1]);
6756 if (!ag) {
6757 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6758 err_code |= ERR_ALERT | ERR_ABORT;
6759 goto out;
6760 }
6761
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006762 cur_arg = 2;
6763
6764 while (*args[cur_arg]) {
6765 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006766 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006767 cur_arg += 2;
6768 continue;
6769 } else {
6770 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6771 file, linenum, args[0]);
6772 err_code |= ERR_ALERT | ERR_FATAL;
6773 goto out;
6774 }
6775 }
6776
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006777 ag->next = userlist->groups;
6778 userlist->groups = ag;
6779
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006780 } else if (!strcmp(args[0], "user")) { /* new user */
6781 struct auth_users *newuser;
6782 int cur_arg;
6783
6784 if (!*args[1]) {
6785 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6786 file, linenum, args[0]);
6787 err_code |= ERR_ALERT | ERR_FATAL;
6788 goto out;
6789 }
William Lallemand4ac9f542015-05-28 18:03:51 +02006790 if (!userlist)
6791 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006792
6793 for (newuser = userlist->users; newuser; newuser = newuser->next)
6794 if (!strcmp(newuser->user, args[1])) {
6795 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6796 file, linenum, args[1], userlist->name);
6797 err_code |= ERR_ALERT;
6798 goto out;
6799 }
6800
6801 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
6802 if (!newuser) {
6803 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6804 err_code |= ERR_ALERT | ERR_ABORT;
6805 goto out;
6806 }
6807
6808 newuser->user = strdup(args[1]);
6809
6810 newuser->next = userlist->users;
6811 userlist->users = newuser;
6812
6813 cur_arg = 2;
6814
6815 while (*args[cur_arg]) {
6816 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006817#ifdef CONFIG_HAP_CRYPT
6818 if (!crypt("", args[cur_arg + 1])) {
6819 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6820 file, linenum, newuser->user);
6821 err_code |= ERR_ALERT | ERR_FATAL;
6822 goto out;
6823 }
6824#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006825 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6826 file, linenum);
6827 err_code |= ERR_ALERT;
6828#endif
6829 newuser->pass = strdup(args[cur_arg + 1]);
6830 cur_arg += 2;
6831 continue;
6832 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6833 newuser->pass = strdup(args[cur_arg + 1]);
6834 newuser->flags |= AU_O_INSECURE;
6835 cur_arg += 2;
6836 continue;
6837 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006838 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006839 cur_arg += 2;
6840 continue;
6841 } else {
6842 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6843 file, linenum, args[0]);
6844 err_code |= ERR_ALERT | ERR_FATAL;
6845 goto out;
6846 }
6847 }
6848 } else {
6849 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6850 err_code |= ERR_ALERT | ERR_FATAL;
6851 }
6852
6853out:
6854 return err_code;
6855}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006856
6857/*
6858 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006859 * Returns the error code, 0 if OK, or any combination of :
6860 * - ERR_ABORT: must abort ASAP
6861 * - ERR_FATAL: we can continue parsing but not start the service
6862 * - ERR_WARN: a warning has been emitted
6863 * - ERR_ALERT: an alert has been emitted
6864 * Only the two first ones can stop processing, the two others are just
6865 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006866 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006867int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006868{
William Lallemand64e84512015-05-12 14:25:37 +02006869 char *thisline;
6870 int linesize = LINESIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006871 FILE *f;
6872 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02006873 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006874 struct cfg_section *cs = NULL;
6875 struct cfg_section *ics;
William Lallemand64e84512015-05-12 14:25:37 +02006876 int readbytes = 0;
6877
6878 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
William Lallemandb2f07452015-05-12 14:27:13 +02006879 Alert("parsing [%s] : out of memory.\n", file);
William Lallemand64e84512015-05-12 14:25:37 +02006880 return -1;
6881 }
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006882
6883 /* Register internal sections */
6884 if (!cfg_register_section("listen", cfg_parse_listen) ||
6885 !cfg_register_section("frontend", cfg_parse_listen) ||
6886 !cfg_register_section("backend", cfg_parse_listen) ||
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006887 !cfg_register_section("defaults", cfg_parse_listen) ||
6888 !cfg_register_section("global", cfg_parse_global) ||
6889 !cfg_register_section("userlist", cfg_parse_users) ||
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006890 !cfg_register_section("peers", cfg_parse_peers) ||
Simon Horman0d16a402015-01-30 11:22:58 +09006891 !cfg_register_section("mailers", cfg_parse_mailers) ||
Baptiste Assmann325137d2015-04-13 23:40:55 +02006892 !cfg_register_section("namespace_list", cfg_parse_netns) ||
6893 !cfg_register_section("resolvers", cfg_parse_resolvers))
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006894 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006895
Willy Tarreaubaaee002006-06-26 02:48:02 +02006896 if ((f=fopen(file,"r")) == NULL)
6897 return -1;
6898
William Lallemandb2f07452015-05-12 14:27:13 +02006899next_line:
William Lallemand64e84512015-05-12 14:25:37 +02006900 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02006901 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006902 char *end;
6903 char *args[MAX_LINE_ARGS + 1];
6904 char *line = thisline;
William Lallemandf9873ba2015-05-05 17:37:14 +02006905 int dquote = 0; /* double quote */
6906 int squote = 0; /* simple quote */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006907
Willy Tarreaubaaee002006-06-26 02:48:02 +02006908 linenum++;
6909
6910 end = line + strlen(line);
6911
William Lallemand64e84512015-05-12 14:25:37 +02006912 if (end-line == linesize-1 && *(end-1) != '\n') {
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006913 /* Check if we reached the limit and the last char is not \n.
6914 * Watch out for the last line without the terminating '\n'!
6915 */
William Lallemand64e84512015-05-12 14:25:37 +02006916 char *newline;
6917 int newlinesize = linesize * 2;
6918
6919 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
6920 if (newline == NULL) {
6921 Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
6922 file, linenum);
6923 err_code |= ERR_ALERT | ERR_FATAL;
6924 continue;
6925 }
6926
6927 readbytes = linesize - 1;
6928 linesize = newlinesize;
6929 thisline = newline;
6930 continue;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006931 }
6932
William Lallemand64e84512015-05-12 14:25:37 +02006933 readbytes = 0;
6934
Willy Tarreaubaaee002006-06-26 02:48:02 +02006935 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006936 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006937 line++;
William Lallemandf9873ba2015-05-05 17:37:14 +02006938
Willy Tarreaubaaee002006-06-26 02:48:02 +02006939 arg = 0;
6940 args[arg] = line;
6941
6942 while (*line && arg < MAX_LINE_ARGS) {
William Lallemandf9873ba2015-05-05 17:37:14 +02006943 if (*line == '"' && !squote) { /* double quote outside single quotes */
6944 if (dquote)
6945 dquote = 0;
6946 else
6947 dquote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02006948 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02006949 end--;
6950 }
6951 else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
6952 if (squote)
6953 squote = 0;
6954 else
6955 squote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02006956 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02006957 end--;
6958 }
6959 else if (*line == '\\' && !squote) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006960 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
6961 * C equivalent value. Other combinations left unchanged (eg: \1).
6962 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006963 int skip = 0;
6964 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
6965 *line = line[1];
6966 skip = 1;
6967 }
6968 else if (line[1] == 'r') {
6969 *line = '\r';
6970 skip = 1;
William Lallemandf9873ba2015-05-05 17:37:14 +02006971 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006972 else if (line[1] == 'n') {
6973 *line = '\n';
6974 skip = 1;
6975 }
6976 else if (line[1] == 't') {
6977 *line = '\t';
6978 skip = 1;
6979 }
6980 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01006981 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006982 unsigned char hex1, hex2;
6983 hex1 = toupper(line[2]) - '0';
6984 hex2 = toupper(line[3]) - '0';
6985 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
6986 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
6987 *line = (hex1<<4) + hex2;
6988 skip = 3;
6989 }
6990 else {
6991 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006992 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006993 }
William Lallemandf9873ba2015-05-05 17:37:14 +02006994 } else if (line[1] == '"') {
6995 *line = '"';
6996 skip = 1;
6997 } else if (line[1] == '\'') {
6998 *line = '\'';
6999 skip = 1;
William Lallemandb2f07452015-05-12 14:27:13 +02007000 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
7001 *line = '$';
7002 skip = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007003 }
7004 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01007005 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02007006 end -= skip;
7007 }
7008 line++;
7009 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007010 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007011 /* end of string, end of loop */
7012 *line = 0;
7013 break;
7014 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007015 else if (!squote && !dquote && isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007016 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007017 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007018 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007019 line++;
7020 args[++arg] = line;
7021 }
William Lallemandb2f07452015-05-12 14:27:13 +02007022 else if (dquote && *line == '$') {
7023 /* environment variables are evaluated inside double quotes */
7024 char *var_beg;
7025 char *var_end;
7026 char save_char;
7027 char *value;
7028 int val_len;
7029 int newlinesize;
7030 int braces = 0;
7031
7032 var_beg = line + 1;
7033 var_end = var_beg;
7034
7035 if (*var_beg == '{') {
7036 var_beg++;
7037 var_end++;
7038 braces = 1;
7039 }
7040
7041 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
7042 Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
7043 err_code |= ERR_ALERT | ERR_FATAL;
7044 goto next_line; /* skip current line */
7045 }
7046
7047 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
7048 var_end++;
7049
7050 save_char = *var_end;
7051 *var_end = '\0';
7052 value = getenv(var_beg);
7053 *var_end = save_char;
7054 val_len = value ? strlen(value) : 0;
7055
7056 if (braces) {
7057 if (*var_end == '}') {
7058 var_end++;
7059 braces = 0;
7060 } else {
7061 Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
7062 err_code |= ERR_ALERT | ERR_FATAL;
7063 goto next_line; /* skip current line */
7064 }
7065 }
7066
7067 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
7068
7069 /* if not enough space in thisline */
7070 if (newlinesize > linesize) {
7071 char *newline;
7072
7073 newline = realloc(thisline, newlinesize * sizeof(*thisline));
7074 if (newline == NULL) {
7075 Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
7076 err_code |= ERR_ALERT | ERR_FATAL;
7077 goto next_line; /* slip current line */
7078 }
7079 /* recompute pointers if realloc returns a new pointer */
7080 if (newline != thisline) {
7081 int i;
7082 int diff;
7083
7084 for (i = 0; i <= arg; i++) {
7085 diff = args[i] - thisline;
7086 args[i] = newline + diff;
7087 }
7088
7089 diff = var_end - thisline;
7090 var_end = newline + diff;
7091 diff = end - thisline;
7092 end = newline + diff;
7093 diff = line - thisline;
7094 line = newline + diff;
7095 thisline = newline;
7096 }
7097 linesize = newlinesize;
7098 }
7099
7100 /* insert value inside the line */
7101 memmove(line + val_len, var_end, end - var_end + 1);
7102 memcpy(line, value, val_len);
7103 end += val_len - (var_end - line);
7104 line += val_len;
7105 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007106 else {
7107 line++;
7108 }
7109 }
William Lallemandb2f07452015-05-12 14:27:13 +02007110
William Lallemandf9873ba2015-05-05 17:37:14 +02007111 if (dquote) {
7112 Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
7113 err_code |= ERR_ALERT | ERR_FATAL;
7114 }
7115
7116 if (squote) {
7117 Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
7118 err_code |= ERR_ALERT | ERR_FATAL;
7119 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007120
7121 /* empty line */
7122 if (!**args)
7123 continue;
7124
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007125 if (*line) {
7126 /* we had to stop due to too many args.
7127 * Let's terminate the string, print the offending part then cut the
7128 * last arg.
7129 */
7130 while (*line && *line != '#' && *line != '\n' && *line != '\r')
7131 line++;
7132 *line = '\0';
7133
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01007134 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01007135 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007136 err_code |= ERR_ALERT | ERR_FATAL;
7137 args[arg] = line;
7138 }
7139
Willy Tarreau540abe42007-05-02 20:50:16 +02007140 /* zero out remaining args and ensure that at least one entry
7141 * is zeroed out.
7142 */
7143 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007144 args[arg] = line;
7145 }
7146
Willy Tarreau3842f002009-06-14 11:39:52 +02007147 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007148 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02007149 char *tmp;
7150
Willy Tarreau3842f002009-06-14 11:39:52 +02007151 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02007152 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007153 for (arg=0; *args[arg+1]; arg++)
7154 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02007155 *tmp = '\0'; // fix the next arg to \0
7156 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007157 }
Willy Tarreau3842f002009-06-14 11:39:52 +02007158 else if (!strcmp(args[0], "default")) {
7159 kwm = KWM_DEF;
7160 for (arg=0; *args[arg+1]; arg++)
7161 args[arg] = args[arg+1]; // shift args after inversion
7162 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007163
William Lallemand0f99e342011-10-12 17:50:54 +02007164 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
7165 strcmp(args[0], "log") != 0) {
7166 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02007167 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007168 }
7169
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007170 /* detect section start */
7171 list_for_each_entry(ics, &sections, list) {
7172 if (strcmp(args[0], ics->section_name) == 0) {
7173 cursection = ics->section_name;
7174 cs = ics;
7175 break;
7176 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007177 }
7178
Willy Tarreaubaaee002006-06-26 02:48:02 +02007179 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007180 if (cs)
7181 err_code |= cs->section_parser(file, linenum, args, kwm);
7182 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007183 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007184 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007185 }
Willy Tarreau058e9072009-07-20 09:30:05 +02007186
7187 if (err_code & ERR_ABORT)
7188 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007189 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01007190 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02007191 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007192 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02007193 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007194}
7195
Willy Tarreau64ab6072014-09-16 12:17:36 +02007196/* This function propagates processes from frontend <from> to backend <to> so
7197 * that it is always guaranteed that a backend pointed to by a frontend is
7198 * bound to all of its processes. After that, if the target is a "listen"
7199 * instance, the function recursively descends the target's own targets along
Willy Tarreau98d04852015-05-26 12:18:29 +02007200 * default_backend and use_backend rules. Since the bits are
Willy Tarreau64ab6072014-09-16 12:17:36 +02007201 * checked first to ensure that <to> is already bound to all processes of
7202 * <from>, there is no risk of looping and we ensure to follow the shortest
7203 * path to the destination.
7204 *
7205 * It is possible to set <to> to NULL for the first call so that the function
7206 * takes care of visiting the initial frontend in <from>.
7207 *
7208 * It is important to note that the function relies on the fact that all names
7209 * have already been resolved.
7210 */
7211void propagate_processes(struct proxy *from, struct proxy *to)
7212{
7213 struct switching_rule *rule;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007214
7215 if (to) {
7216 /* check whether we need to go down */
7217 if (from->bind_proc &&
7218 (from->bind_proc & to->bind_proc) == from->bind_proc)
7219 return;
7220
7221 if (!from->bind_proc && !to->bind_proc)
7222 return;
7223
7224 to->bind_proc = from->bind_proc ?
7225 (to->bind_proc | from->bind_proc) : 0;
7226
7227 /* now propagate down */
7228 from = to;
7229 }
7230
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01007231 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02007232 return;
7233
Willy Tarreauf6b70012014-12-18 14:00:43 +01007234 if (from->state == PR_STSTOPPED)
7235 return;
7236
Willy Tarreau64ab6072014-09-16 12:17:36 +02007237 /* default_backend */
7238 if (from->defbe.be)
7239 propagate_processes(from, from->defbe.be);
7240
7241 /* use_backend */
7242 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02007243 if (rule->dynamic)
7244 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007245 to = rule->be.backend;
7246 propagate_processes(from, to);
7247 }
Willy Tarreau64ab6072014-09-16 12:17:36 +02007248}
7249
Willy Tarreaubb925012009-07-23 13:36:36 +02007250/*
7251 * Returns the error code, 0 if OK, or any combination of :
7252 * - ERR_ABORT: must abort ASAP
7253 * - ERR_FATAL: we can continue parsing but not start the service
7254 * - ERR_WARN: a warning has been emitted
7255 * - ERR_ALERT: an alert has been emitted
7256 * Only the two first ones can stop processing, the two others are just
7257 * indicators.
7258 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007259int check_config_validity()
7260{
7261 int cfgerr = 0;
7262 struct proxy *curproxy = NULL;
7263 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02007264 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007265 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007266 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007267
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007268 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007269 /*
7270 * Now, check for the integrity of all that we have collected.
7271 */
7272
7273 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02007274 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007275
Willy Tarreau193b8c62012-11-22 00:17:38 +01007276 if (!global.tune.max_http_hdr)
7277 global.tune.max_http_hdr = MAX_HTTP_HDR;
7278
7279 if (!global.tune.cookie_len)
7280 global.tune.cookie_len = CAPTURE_LEN;
7281
7282 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
7283
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007284 /* Post initialisation of the users and groups lists. */
7285 err_code = userlist_postinit();
7286 if (err_code != ERR_NONE)
7287 goto out;
7288
Willy Tarreau55bc0f82009-03-15 14:51:53 +01007289 /* first, we will invert the proxy list order */
7290 curproxy = NULL;
7291 while (proxy) {
7292 struct proxy *next;
7293
7294 next = proxy->next;
7295 proxy->next = curproxy;
7296 curproxy = proxy;
7297 if (!next)
7298 break;
7299 proxy = next;
7300 }
7301
Willy Tarreau419ead82014-09-16 13:41:21 +02007302 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007303 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007304 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01007305 struct sticking_rule *mrule;
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007306 struct act_rule *trule;
7307 struct act_rule *hrqrule;
Dragan Dosen1322d092015-09-22 16:05:32 +02007308 struct logsrv *tmplogsrv;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007309 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01007310 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007311
Willy Tarreau050536d2012-10-04 08:47:34 +02007312 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007313 /* proxy ID not set, use automatic numbering with first
7314 * spare entry starting with next_pxid.
7315 */
7316 next_pxid = get_next_id(&used_proxy_id, next_pxid);
7317 curproxy->conf.id.key = curproxy->uuid = next_pxid;
7318 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007319 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007320 next_pxid++;
7321
Willy Tarreau55ea7572007-06-17 19:56:27 +02007322
Willy Tarreaubaaee002006-06-26 02:48:02 +02007323 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02007324 /* ensure we don't keep listeners uselessly bound */
7325 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02007326 free((void *)curproxy->table.peers.name);
7327 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007328 continue;
7329 }
7330
Willy Tarreau102df612014-05-07 23:56:38 +02007331 /* Check multi-process mode compatibility for the current proxy */
7332
7333 if (curproxy->bind_proc) {
7334 /* an explicit bind-process was specified, let's check how many
7335 * processes remain.
7336 */
David Carliere6c39412015-07-02 07:00:17 +00007337 nbproc = my_popcountl(curproxy->bind_proc);
Willy Tarreau102df612014-05-07 23:56:38 +02007338
7339 curproxy->bind_proc &= nbits(global.nbproc);
7340 if (!curproxy->bind_proc && nbproc == 1) {
7341 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);
7342 curproxy->bind_proc = 1;
7343 }
7344 else if (!curproxy->bind_proc && nbproc > 1) {
7345 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);
7346 curproxy->bind_proc = 0;
7347 }
7348 }
7349
Willy Tarreau3d209582014-05-09 17:06:11 +02007350 /* check and reduce the bind-proc of each listener */
7351 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7352 unsigned long mask;
7353
7354 if (!bind_conf->bind_proc)
7355 continue;
7356
7357 mask = nbits(global.nbproc);
7358 if (curproxy->bind_proc)
7359 mask &= curproxy->bind_proc;
7360 /* mask cannot be null here thanks to the previous checks */
7361
David Carliere6c39412015-07-02 07:00:17 +00007362 nbproc = my_popcountl(bind_conf->bind_proc);
Willy Tarreau3d209582014-05-09 17:06:11 +02007363 bind_conf->bind_proc &= mask;
7364
7365 if (!bind_conf->bind_proc && nbproc == 1) {
7366 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",
7367 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7368 bind_conf->bind_proc = mask & ~(mask - 1);
7369 }
7370 else if (!bind_conf->bind_proc && nbproc > 1) {
7371 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",
7372 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7373 bind_conf->bind_proc = 0;
7374 }
7375 }
7376
Willy Tarreauff01a212009-03-15 13:46:16 +01007377 switch (curproxy->mode) {
7378 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007379 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007380 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007381 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
7382 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007383 cfgerr++;
7384 }
7385
7386 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007387 Warning("config : servers will be ignored for %s '%s'.\n",
7388 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007389 break;
7390
7391 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007392 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007393 break;
7394
7395 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01007396 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01007397 break;
7398 }
7399
Willy Tarreauf3934b82015-08-11 11:36:45 +02007400 if ((curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->conf.listeners)) {
7401 Warning("config : %s '%s' has no 'bind' directive. Please declare it as a backend if this was intended.\n",
7402 proxy_type_str(curproxy), curproxy->id);
7403 err_code |= ERR_WARN;
7404 }
7405
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007406 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007407 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007408 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007409 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
7410 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007411 cfgerr++;
7412 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007413#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007414 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007415 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
7416 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007417 cfgerr++;
7418 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007419#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02007420 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007421 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
7422 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007423 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007424 }
7425 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02007426 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007427 /* If no LB algo is set in a backend, and we're not in
7428 * transparent mode, dispatch mode nor proxy mode, we
7429 * want to use balance roundrobin by default.
7430 */
7431 curproxy->lbprm.algo &= ~BE_LB_ALGO;
7432 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007433 }
7434 }
Willy Tarreau193cf932007-09-17 10:17:23 +02007435
Willy Tarreau1620ec32011-08-06 17:05:02 +02007436 if (curproxy->options & PR_O_DISPATCH)
7437 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
7438 else if (curproxy->options & PR_O_HTTP_PROXY)
7439 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
7440 else if (curproxy->options & PR_O_TRANSP)
7441 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01007442
Willy Tarreau1620ec32011-08-06 17:05:02 +02007443 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
7444 if (curproxy->options & PR_O_DISABLE404) {
7445 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7446 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
7447 err_code |= ERR_WARN;
7448 curproxy->options &= ~PR_O_DISABLE404;
7449 }
7450 if (curproxy->options2 & PR_O2_CHK_SNDST) {
7451 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7452 "send-state", proxy_type_str(curproxy), curproxy->id);
7453 err_code |= ERR_WARN;
7454 curproxy->options &= ~PR_O2_CHK_SNDST;
7455 }
Willy Tarreauef781042010-01-27 11:53:01 +01007456 }
7457
Simon Horman98637e52014-06-20 12:30:16 +09007458 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
7459 if (!global.external_check) {
7460 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
7461 curproxy->id, "option external-check");
7462 cfgerr++;
7463 }
7464 if (!curproxy->check_command) {
7465 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
7466 curproxy->id, "option external-check");
7467 cfgerr++;
7468 }
7469 }
7470
Simon Horman64e34162015-02-06 11:11:57 +09007471 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007472 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
7473 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Pieter Baauw8669e972015-08-17 00:45:05 +02007474 "'email-alert from', 'email-alert level' 'email-alert mailers', "
7475 "'email-alert myhostname', or 'email-alert to' "
7476 "requires each of 'email-alert from', 'email-alert mailers' and 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007477 "to be present).\n",
7478 proxy_type_str(curproxy), curproxy->id);
7479 err_code |= ERR_WARN;
7480 free_email_alert(curproxy);
7481 }
7482 if (!curproxy->email_alert.myhostname)
Cyril Bontée22bfd62015-12-04 03:07:07 +01007483 curproxy->email_alert.myhostname = strdup(hostname);
Simon Horman9dc49962015-01-30 11:22:59 +09007484 }
7485
Simon Horman98637e52014-06-20 12:30:16 +09007486 if (curproxy->check_command) {
7487 int clear = 0;
7488 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7489 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7490 "external-check command", proxy_type_str(curproxy), curproxy->id);
7491 err_code |= ERR_WARN;
7492 clear = 1;
7493 }
7494 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
Ben Cabot49795eb2015-09-16 12:07:51 +01007495 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-check path' is not set.\n",
Simon Horman98637e52014-06-20 12:30:16 +09007496 curproxy->id, "external-check command");
7497 cfgerr++;
7498 }
7499 if (clear) {
7500 free(curproxy->check_command);
7501 curproxy->check_command = NULL;
7502 }
7503 }
7504
7505 if (curproxy->check_path) {
7506 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7507 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7508 "external-check path", proxy_type_str(curproxy), curproxy->id);
7509 err_code |= ERR_WARN;
7510 free(curproxy->check_path);
7511 curproxy->check_path = NULL;
7512 }
7513 }
7514
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007515 /* if a default backend was specified, let's find it */
7516 if (curproxy->defbe.name) {
7517 struct proxy *target;
7518
Willy Tarreauafb39922015-05-26 12:04:09 +02007519 target = proxy_be_by_name(curproxy->defbe.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007520 if (!target) {
7521 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
7522 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007523 cfgerr++;
7524 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007525 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
7526 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02007527 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007528 } else if (target->mode != curproxy->mode &&
7529 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7530
7531 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) as its default backend (see 'mode').\n",
7532 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7533 curproxy->conf.file, curproxy->conf.line,
7534 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7535 target->conf.file, target->conf.line);
7536 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007537 } else {
7538 free(curproxy->defbe.name);
7539 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01007540
7541 /* Emit a warning if this proxy also has some servers */
7542 if (curproxy->srv) {
7543 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
7544 curproxy->id);
7545 err_code |= ERR_WARN;
7546 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007547 }
7548 }
7549
Willy Tarreau55ea7572007-06-17 19:56:27 +02007550 /* find the target proxy for 'use_backend' rules */
7551 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007552 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007553 struct logformat_node *node;
7554 char *pxname;
7555
7556 /* Try to parse the string as a log format expression. If the result
7557 * of the parsing is only one entry containing a simple string, then
7558 * it's a standard string corresponding to a static rule, thus the
7559 * parsing is cancelled and be.name is restored to be resolved.
7560 */
7561 pxname = rule->be.name;
7562 LIST_INIT(&rule->be.expr);
7563 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
7564 curproxy->conf.args.file, curproxy->conf.args.line);
7565 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
7566
7567 if (!LIST_ISEMPTY(&rule->be.expr)) {
7568 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
7569 rule->dynamic = 1;
7570 free(pxname);
7571 continue;
7572 }
7573 /* simple string: free the expression and fall back to static rule */
7574 free(node->arg);
7575 free(node);
7576 }
7577
7578 rule->dynamic = 0;
7579 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007580
Willy Tarreauafb39922015-05-26 12:04:09 +02007581 target = proxy_be_by_name(rule->be.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007582 if (!target) {
7583 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
7584 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007585 cfgerr++;
7586 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007587 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
7588 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007589 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007590 } else if (target->mode != curproxy->mode &&
7591 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7592
7593 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) in a 'use_backend' rule (see 'mode').\n",
7594 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7595 curproxy->conf.file, curproxy->conf.line,
7596 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7597 target->conf.file, target->conf.line);
7598 cfgerr++;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007599 } else {
7600 free((void *)rule->be.name);
7601 rule->be.backend = target;
7602 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007603 }
7604
Willy Tarreau64ab6072014-09-16 12:17:36 +02007605 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007606 list_for_each_entry(srule, &curproxy->server_rules, list) {
7607 struct server *target = findserver(curproxy, srule->srv.name);
7608
7609 if (!target) {
7610 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7611 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7612 cfgerr++;
7613 continue;
7614 }
7615 free((void *)srule->srv.name);
7616 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007617 }
7618
Emeric Brunb982a3d2010-01-04 15:45:53 +01007619 /* find the target table for 'stick' rules */
7620 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7621 struct proxy *target;
7622
Emeric Brun1d33b292010-01-04 15:47:17 +01007623 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7624 if (mrule->flags & STK_IS_STORE)
7625 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7626
Emeric Brunb982a3d2010-01-04 15:45:53 +01007627 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007628 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007629 else
7630 target = curproxy;
7631
7632 if (!target) {
7633 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7634 curproxy->id, mrule->table.name);
7635 cfgerr++;
7636 }
7637 else if (target->table.size == 0) {
7638 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7639 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7640 cfgerr++;
7641 }
Willy Tarreau12785782012-04-27 21:37:17 +02007642 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7643 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007644 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7645 cfgerr++;
7646 }
7647 else {
7648 free((void *)mrule->table.name);
7649 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007650 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007651 }
7652 }
7653
7654 /* find the target table for 'store response' rules */
7655 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7656 struct proxy *target;
7657
Emeric Brun1d33b292010-01-04 15:47:17 +01007658 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7659
Emeric Brunb982a3d2010-01-04 15:45:53 +01007660 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007661 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007662 else
7663 target = curproxy;
7664
7665 if (!target) {
7666 Alert("Proxy '%s': unable to find store table '%s'.\n",
7667 curproxy->id, mrule->table.name);
7668 cfgerr++;
7669 }
7670 else if (target->table.size == 0) {
7671 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7672 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7673 cfgerr++;
7674 }
Willy Tarreau12785782012-04-27 21:37:17 +02007675 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7676 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007677 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7678 cfgerr++;
7679 }
7680 else {
7681 free((void *)mrule->table.name);
7682 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007683 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007684 }
7685 }
7686
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007687 /* find the target table for 'tcp-request' layer 4 rules */
7688 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
7689 struct proxy *target;
7690
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007691 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007692 continue;
7693
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007694 if (trule->arg.trk_ctr.table.n)
7695 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007696 else
7697 target = curproxy;
7698
7699 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007700 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007701 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007702 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007703 cfgerr++;
7704 }
7705 else if (target->table.size == 0) {
7706 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007707 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007708 cfgerr++;
7709 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007710 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007711 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007712 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007713 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007714 cfgerr++;
7715 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007716 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007717 free(trule->arg.trk_ctr.table.n);
7718 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007719 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007720 * to pass a list of counters to track and allocate them right here using
7721 * stktable_alloc_data_type().
7722 */
7723 }
7724 }
7725
Willy Tarreaud1f96522010-08-03 19:34:32 +02007726 /* find the target table for 'tcp-request' layer 6 rules */
7727 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7728 struct proxy *target;
7729
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007730 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02007731 continue;
7732
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007733 if (trule->arg.trk_ctr.table.n)
7734 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007735 else
7736 target = curproxy;
7737
7738 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007739 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007740 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007741 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02007742 cfgerr++;
7743 }
7744 else if (target->table.size == 0) {
7745 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007746 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007747 cfgerr++;
7748 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007749 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007750 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007751 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007752 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007753 cfgerr++;
7754 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02007755 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007756 free(trule->arg.trk_ctr.table.n);
7757 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007758 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02007759 * to pass a list of counters to track and allocate them right here using
7760 * stktable_alloc_data_type().
7761 */
7762 }
7763 }
7764
Baptiste Assmanne9544932015-11-03 23:31:35 +01007765 /* parse http-request capture rules to ensure id really exists */
7766 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7767 if (hrqrule->action != ACT_CUSTOM ||
7768 hrqrule->action_ptr != http_action_req_capture_by_id)
7769 continue;
7770
7771 if (hrqrule->arg.capid.idx >= curproxy->nb_req_cap) {
7772 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-request capture rule.\n",
7773 curproxy->id, hrqrule->arg.capid.idx);
7774 cfgerr++;
7775 }
7776 }
7777
7778 /* parse http-response capture rules to ensure id really exists */
7779 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
7780 if (hrqrule->action != ACT_CUSTOM ||
7781 hrqrule->action_ptr != http_action_res_capture_by_id)
7782 continue;
7783
7784 if (hrqrule->arg.capid.idx >= curproxy->nb_rsp_cap) {
7785 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-response capture rule.\n",
7786 curproxy->id, hrqrule->arg.capid.idx);
7787 cfgerr++;
7788 }
7789 }
7790
Willy Tarreau09448f72014-06-25 18:12:15 +02007791 /* find the target table for 'http-request' layer 7 rules */
7792 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7793 struct proxy *target;
7794
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007795 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau09448f72014-06-25 18:12:15 +02007796 continue;
7797
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007798 if (hrqrule->arg.trk_ctr.table.n)
7799 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
Willy Tarreau09448f72014-06-25 18:12:15 +02007800 else
7801 target = curproxy;
7802
7803 if (!target) {
7804 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007805 curproxy->id, hrqrule->arg.trk_ctr.table.n,
Willy Tarreau09448f72014-06-25 18:12:15 +02007806 http_req_trk_idx(hrqrule->action));
7807 cfgerr++;
7808 }
7809 else if (target->table.size == 0) {
7810 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007811 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau09448f72014-06-25 18:12:15 +02007812 cfgerr++;
7813 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007814 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau09448f72014-06-25 18:12:15 +02007815 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007816 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau09448f72014-06-25 18:12:15 +02007817 http_req_trk_idx(hrqrule->action));
7818 cfgerr++;
7819 }
7820 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007821 free(hrqrule->arg.trk_ctr.table.n);
7822 hrqrule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau09448f72014-06-25 18:12:15 +02007823 /* Note: if we decide to enhance the track-sc syntax, we may be able
7824 * to pass a list of counters to track and allocate them right here using
7825 * stktable_alloc_data_type().
7826 */
7827 }
7828 }
7829
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02007830 /* move any "block" rules at the beginning of the http-request rules */
7831 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
7832 /* insert block_rules into http_req_rules at the beginning */
7833 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
7834 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
7835 curproxy->block_rules.n->p = &curproxy->http_req_rules;
7836 curproxy->http_req_rules.n = curproxy->block_rules.n;
7837 LIST_INIT(&curproxy->block_rules);
7838 }
7839
Emeric Brun32da3c42010-09-23 18:39:19 +02007840 if (curproxy->table.peers.name) {
7841 struct peers *curpeers = peers;
7842
7843 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
7844 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
7845 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01007846 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02007847 break;
7848 }
7849 }
7850
7851 if (!curpeers) {
7852 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
7853 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007854 free((void *)curproxy->table.peers.name);
7855 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007856 cfgerr++;
7857 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02007858 else if (curpeers->state == PR_STSTOPPED) {
7859 /* silently disable this peers section */
7860 curproxy->table.peers.p = NULL;
7861 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007862 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02007863 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
7864 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007865 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007866 cfgerr++;
7867 }
7868 }
7869
Simon Horman9dc49962015-01-30 11:22:59 +09007870
7871 if (curproxy->email_alert.mailers.name) {
7872 struct mailers *curmailers = mailers;
7873
7874 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
7875 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
7876 free(curproxy->email_alert.mailers.name);
7877 curproxy->email_alert.mailers.m = curmailers;
7878 curmailers->users++;
7879 break;
7880 }
7881 }
7882
7883 if (!curmailers) {
7884 Alert("Proxy '%s': unable to find mailers '%s'.\n",
7885 curproxy->id, curproxy->email_alert.mailers.name);
7886 free_email_alert(curproxy);
7887 cfgerr++;
7888 }
7889 }
7890
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007891 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01007892 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007893 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
7894 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
7895 "proxy", curproxy->id);
7896 cfgerr++;
7897 goto out_uri_auth_compat;
7898 }
7899
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007900 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007901 const char *uri_auth_compat_req[10];
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007902 struct act_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01007903 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007904
Willy Tarreau95fa4692010-02-01 13:05:50 +01007905 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
7906 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007907
7908 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007909 uri_auth_compat_req[i++] = "realm";
7910 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
7911 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007912
Willy Tarreau95fa4692010-02-01 13:05:50 +01007913 uri_auth_compat_req[i++] = "unless";
7914 uri_auth_compat_req[i++] = "{";
7915 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
7916 uri_auth_compat_req[i++] = "}";
7917 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007918
Willy Tarreauff011f22011-01-06 17:51:27 +01007919 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
7920 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007921 cfgerr++;
7922 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007923 }
7924
Willy Tarreauff011f22011-01-06 17:51:27 +01007925 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01007926
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007927 if (curproxy->uri_auth->auth_realm) {
7928 free(curproxy->uri_auth->auth_realm);
7929 curproxy->uri_auth->auth_realm = NULL;
7930 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007931
7932 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007933 }
7934out_uri_auth_compat:
7935
Dragan Dosen43885c72015-10-01 13:18:13 +02007936 /* check whether we have a log server that uses RFC5424 log format */
Dragan Dosen1322d092015-09-22 16:05:32 +02007937 list_for_each_entry(tmplogsrv, &curproxy->logsrvs, list) {
Dragan Dosen43885c72015-10-01 13:18:13 +02007938 if (tmplogsrv->format == LOG_FORMAT_RFC5424) {
7939 if (!curproxy->conf.logformat_sd_string) {
7940 /* set the default logformat_sd_string */
7941 curproxy->conf.logformat_sd_string = default_rfc5424_sd_log_format;
7942 }
Dragan Dosen1322d092015-09-22 16:05:32 +02007943 break;
Dragan Dosen1322d092015-09-22 16:05:32 +02007944 }
Dragan Dosen1322d092015-09-22 16:05:32 +02007945 }
Dragan Dosen68d2e3a2015-09-19 22:35:44 +02007946
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007947 /* compile the log format */
7948 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02007949 if (curproxy->conf.logformat_string != default_http_log_format &&
7950 curproxy->conf.logformat_string != default_tcp_log_format &&
7951 curproxy->conf.logformat_string != clf_http_log_format)
7952 free(curproxy->conf.logformat_string);
7953 curproxy->conf.logformat_string = NULL;
7954 free(curproxy->conf.lfs_file);
7955 curproxy->conf.lfs_file = NULL;
7956 curproxy->conf.lfs_line = 0;
Dragan Dosen0b85ece2015-09-25 19:17:44 +02007957
7958 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
7959 free(curproxy->conf.logformat_sd_string);
7960 curproxy->conf.logformat_sd_string = NULL;
7961 free(curproxy->conf.lfsd_file);
7962 curproxy->conf.lfsd_file = NULL;
7963 curproxy->conf.lfsd_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007964 }
7965
Willy Tarreau62a61232013-04-12 18:13:46 +02007966 if (curproxy->conf.logformat_string) {
7967 curproxy->conf.args.ctx = ARGC_LOG;
7968 curproxy->conf.args.file = curproxy->conf.lfs_file;
7969 curproxy->conf.args.line = curproxy->conf.lfs_line;
7970 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007971 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007972 curproxy->conf.args.file = NULL;
7973 curproxy->conf.args.line = 0;
7974 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007975
Dragan Dosen0b85ece2015-09-25 19:17:44 +02007976 if (curproxy->conf.logformat_sd_string) {
7977 curproxy->conf.args.ctx = ARGC_LOGSD;
7978 curproxy->conf.args.file = curproxy->conf.lfsd_file;
7979 curproxy->conf.args.line = curproxy->conf.lfsd_line;
7980 parse_logformat_string(curproxy->conf.logformat_sd_string, curproxy, &curproxy->logformat_sd, LOG_OPT_MANDATORY,
7981 SMP_VAL_FE_LOG_END, curproxy->conf.lfsd_file, curproxy->conf.lfsd_line);
7982 add_to_logformat_list(NULL, NULL, LF_SEPARATOR, &curproxy->logformat_sd);
7983 curproxy->conf.args.file = NULL;
7984 curproxy->conf.args.line = 0;
7985 }
7986
Willy Tarreau62a61232013-04-12 18:13:46 +02007987 if (curproxy->conf.uniqueid_format_string) {
7988 curproxy->conf.args.ctx = ARGC_UIF;
7989 curproxy->conf.args.file = curproxy->conf.uif_file;
7990 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01007991 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Godbachd9722032014-12-18 15:44:58 +08007992 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007993 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007994 curproxy->conf.args.file = NULL;
7995 curproxy->conf.args.line = 0;
7996 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007997
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007998 /* only now we can check if some args remain unresolved.
7999 * This must be done after the users and groups resolution.
8000 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008001 cfgerr += smp_resolve_args(curproxy);
8002 if (!cfgerr)
8003 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01008004
Willy Tarreau2738a142006-07-08 17:28:09 +02008005 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008006 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02008007 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02008008 (!curproxy->timeout.connect ||
8009 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008010 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02008011 " | While not properly invalid, you will certainly encounter various problems\n"
8012 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01008013 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008014 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008015 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02008016 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02008017
Willy Tarreau1fa31262007-12-03 00:36:16 +01008018 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
8019 * We must still support older configurations, so let's find out whether those
8020 * parameters have been set or must be copied from contimeouts.
8021 */
8022 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008023 if (!curproxy->timeout.tarpit ||
8024 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008025 /* tarpit timeout not set. We search in the following order:
8026 * default.tarpit, curr.connect, default.connect.
8027 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008028 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008029 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008030 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008031 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008032 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008033 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008034 }
8035 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008036 (!curproxy->timeout.queue ||
8037 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008038 /* queue timeout not set. We search in the following order:
8039 * default.queue, curr.connect, default.connect.
8040 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008041 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008042 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008043 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008044 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008045 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008046 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008047 }
8048 }
8049
Willy Tarreau1620ec32011-08-06 17:05:02 +02008050 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01008051 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
8052 curproxy->check_req = (char *)malloc(curproxy->check_len);
8053 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02008054 }
8055
Willy Tarreau215663d2014-06-13 18:30:23 +02008056 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
8057 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
8058 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
8059 proxy_type_str(curproxy), curproxy->id);
8060 err_code |= ERR_WARN;
8061 }
8062
Willy Tarreau193b8c62012-11-22 00:17:38 +01008063 /* ensure that cookie capture length is not too large */
8064 if (curproxy->capture_len >= global.tune.cookie_len) {
8065 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
8066 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
8067 err_code |= ERR_WARN;
8068 curproxy->capture_len = global.tune.cookie_len - 1;
8069 }
8070
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008071 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01008072 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008073 curproxy->req_cap_pool = create_pool("ptrcap",
8074 curproxy->nb_req_cap * sizeof(char *),
8075 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008076 }
8077
8078 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008079 curproxy->rsp_cap_pool = create_pool("ptrcap",
8080 curproxy->nb_rsp_cap * sizeof(char *),
8081 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008082 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008083
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02008084 switch (curproxy->load_server_state_from_file) {
8085 case PR_SRV_STATE_FILE_UNSPEC:
8086 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
8087 break;
8088 case PR_SRV_STATE_FILE_GLOBAL:
8089 if (!global.server_state_file) {
8090 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",
8091 curproxy->id);
8092 err_code |= ERR_WARN;
8093 }
8094 break;
8095 }
8096
Willy Tarreaubaaee002006-06-26 02:48:02 +02008097 /* first, we will invert the servers list order */
8098 newsrv = NULL;
8099 while (curproxy->srv) {
8100 struct server *next;
8101
8102 next = curproxy->srv->next;
8103 curproxy->srv->next = newsrv;
8104 newsrv = curproxy->srv;
8105 if (!next)
8106 break;
8107 curproxy->srv = next;
8108 }
8109
Willy Tarreau17edc812014-01-03 12:14:34 +01008110 /* Check that no server name conflicts. This causes trouble in the stats.
8111 * We only emit a warning for the first conflict affecting each server,
8112 * in order to avoid combinatory explosion if all servers have the same
8113 * name. We do that only for servers which do not have an explicit ID,
8114 * because these IDs were made also for distinguishing them and we don't
8115 * want to annoy people who correctly manage them.
8116 */
8117 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
8118 struct server *other_srv;
8119
8120 if (newsrv->puid)
8121 continue;
8122
8123 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
8124 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
8125 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
8126 newsrv->conf.file, newsrv->conf.line,
8127 proxy_type_str(curproxy), curproxy->id,
8128 newsrv->id, other_srv->conf.line);
8129 break;
8130 }
8131 }
8132 }
8133
Willy Tarreaudd701652010-05-25 23:03:02 +02008134 /* assign automatic UIDs to servers which don't have one yet */
8135 next_id = 1;
8136 newsrv = curproxy->srv;
8137 while (newsrv != NULL) {
8138 if (!newsrv->puid) {
8139 /* server ID not set, use automatic numbering with first
8140 * spare entry starting with next_svid.
8141 */
8142 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
8143 newsrv->conf.id.key = newsrv->puid = next_id;
8144 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
8145 }
8146 next_id++;
8147 newsrv = newsrv->next;
8148 }
8149
Willy Tarreau20697042007-11-15 23:26:18 +01008150 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01008151 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02008152
Willy Tarreau62c3be22012-01-20 13:12:32 +01008153 /*
8154 * If this server supports a maxconn parameter, it needs a dedicated
8155 * tasks to fill the emptied slots when a connection leaves.
8156 * Also, resolve deferred tracking dependency if needed.
8157 */
8158 newsrv = curproxy->srv;
8159 while (newsrv != NULL) {
8160 if (newsrv->minconn > newsrv->maxconn) {
8161 /* Only 'minconn' was specified, or it was higher than or equal
8162 * to 'maxconn'. Let's turn this into maxconn and clean it, as
8163 * this will avoid further useless expensive computations.
8164 */
8165 newsrv->maxconn = newsrv->minconn;
8166 } else if (newsrv->maxconn && !newsrv->minconn) {
8167 /* minconn was not specified, so we set it to maxconn */
8168 newsrv->minconn = newsrv->maxconn;
8169 }
8170
Emeric Brun01f8e2f2012-05-18 16:02:00 +02008171#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02008172 if (newsrv->use_ssl || newsrv->check.use_ssl)
8173 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02008174#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02008175
Willy Tarreau2f075e92013-12-03 11:11:34 +01008176 /* set the check type on the server */
8177 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
8178
Willy Tarreau62c3be22012-01-20 13:12:32 +01008179 if (newsrv->trackit) {
8180 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02008181 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008182 char *pname, *sname;
8183
8184 pname = newsrv->trackit;
8185 sname = strrchr(pname, '/');
8186
8187 if (sname)
8188 *sname++ = '\0';
8189 else {
8190 sname = pname;
8191 pname = NULL;
8192 }
8193
8194 if (pname) {
Willy Tarreau9e0bb102015-05-26 11:24:42 +02008195 px = proxy_be_by_name(pname);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008196 if (!px) {
8197 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
8198 proxy_type_str(curproxy), curproxy->id,
8199 newsrv->id, pname);
8200 cfgerr++;
8201 goto next_srv;
8202 }
8203 } else
8204 px = curproxy;
8205
8206 srv = findserver(px, sname);
8207 if (!srv) {
8208 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
8209 proxy_type_str(curproxy), curproxy->id,
8210 newsrv->id, sname);
8211 cfgerr++;
8212 goto next_srv;
8213 }
8214
Willy Tarreau32091232014-05-16 13:52:00 +02008215 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
8216 !(srv->agent.state & CHK_ST_CONFIGURED) &&
8217 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01008218 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02008219 "tracking as it does not have any check nor agent enabled.\n",
8220 proxy_type_str(curproxy), curproxy->id,
8221 newsrv->id, px->id, srv->id);
8222 cfgerr++;
8223 goto next_srv;
8224 }
8225
8226 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
8227
8228 if (loop) {
8229 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
8230 "belongs to a tracking chain looping back to %s/%s.\n",
8231 proxy_type_str(curproxy), curproxy->id,
8232 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008233 cfgerr++;
8234 goto next_srv;
8235 }
8236
8237 if (curproxy != px &&
8238 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
8239 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
8240 "tracking: disable-on-404 option inconsistency.\n",
8241 proxy_type_str(curproxy), curproxy->id,
8242 newsrv->id, px->id, srv->id);
8243 cfgerr++;
8244 goto next_srv;
8245 }
8246
8247 /* if the other server is forced disabled, we have to do the same here */
Willy Tarreau20125212014-05-13 19:44:56 +02008248 if (srv->admin & SRV_ADMF_MAINT) {
Willy Tarreaua0066dd2014-05-16 11:25:16 +02008249 newsrv->admin |= SRV_ADMF_IMAINT;
Willy Tarreau892337c2014-05-13 23:41:20 +02008250 newsrv->state = SRV_ST_STOPPED;
Simon Horman125d0992013-02-24 17:23:38 +09008251 newsrv->check.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008252 }
8253
8254 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01008255 newsrv->tracknext = srv->trackers;
8256 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008257
8258 free(newsrv->trackit);
8259 newsrv->trackit = NULL;
8260 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008261
8262 /*
8263 * resolve server's resolvers name and update the resolvers pointer
8264 * accordingly
8265 */
8266 if (newsrv->resolvers_id) {
8267 struct dns_resolvers *curr_resolvers;
8268 int found;
8269
8270 found = 0;
8271 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
8272 if (!strcmp(curr_resolvers->id, newsrv->resolvers_id)) {
8273 found = 1;
8274 break;
8275 }
8276 }
8277
8278 if (!found) {
8279 Alert("config : %s '%s', server '%s': unable to find required resolvers '%s'\n",
8280 proxy_type_str(curproxy), curproxy->id,
8281 newsrv->id, newsrv->resolvers_id);
8282 cfgerr++;
8283 } else {
8284 free(newsrv->resolvers_id);
8285 newsrv->resolvers_id = NULL;
8286 if (newsrv->resolution)
8287 newsrv->resolution->resolvers = curr_resolvers;
8288 }
8289 }
8290 else {
8291 /* if no resolvers section associated to this server
8292 * we can clean up the associated resolution structure
8293 */
8294 if (newsrv->resolution) {
8295 free(newsrv->resolution->hostname_dn);
8296 newsrv->resolution->hostname_dn = NULL;
8297 free(newsrv->resolution);
8298 newsrv->resolution = NULL;
8299 }
8300 }
8301
Willy Tarreau62c3be22012-01-20 13:12:32 +01008302 next_srv:
8303 newsrv = newsrv->next;
8304 }
8305
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008306 /* We have to initialize the server lookup mechanism depending
8307 * on what LB algorithm was choosen.
8308 */
8309
8310 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
8311 switch (curproxy->lbprm.algo & BE_LB_KIND) {
8312 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02008313 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
8314 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8315 init_server_map(curproxy);
8316 } else {
8317 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
8318 fwrr_init_server_groups(curproxy);
8319 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008320 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008321
Willy Tarreau3ebb1162012-02-13 16:57:44 +01008322 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01008323 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
8324 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
8325 fwlc_init_server_tree(curproxy);
8326 } else {
8327 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
8328 fas_init_server_tree(curproxy);
8329 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008330 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008331
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008332 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008333 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
8334 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
8335 chash_init_server_tree(curproxy);
8336 } else {
8337 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8338 init_server_map(curproxy);
8339 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008340 break;
8341 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02008342
8343 if (curproxy->options & PR_O_LOGASAP)
8344 curproxy->to_log &= ~LW_BYTES;
8345
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008346 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008347 (curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->logsrvs) &&
8348 (!LIST_ISEMPTY(&curproxy->logformat) || !LIST_ISEMPTY(&curproxy->logformat_sd))) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008349 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
8350 proxy_type_str(curproxy), curproxy->id);
8351 err_code |= ERR_WARN;
8352 }
8353
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008354 if (curproxy->mode != PR_MODE_HTTP) {
8355 int optnum;
8356
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008357 if (curproxy->uri_auth) {
8358 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
8359 proxy_type_str(curproxy), curproxy->id);
8360 err_code |= ERR_WARN;
8361 curproxy->uri_auth = NULL;
8362 }
8363
Willy Tarreau87cf5142011-08-19 22:57:24 +02008364 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008365 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8366 "forwardfor", proxy_type_str(curproxy), curproxy->id);
8367 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02008368 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008369 }
8370
8371 if (curproxy->options & PR_O_ORGTO) {
8372 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8373 "originalto", proxy_type_str(curproxy), curproxy->id);
8374 err_code |= ERR_WARN;
8375 curproxy->options &= ~PR_O_ORGTO;
8376 }
8377
8378 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
8379 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
8380 (curproxy->cap & cfg_opts[optnum].cap) &&
8381 (curproxy->options & cfg_opts[optnum].val)) {
8382 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8383 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
8384 err_code |= ERR_WARN;
8385 curproxy->options &= ~cfg_opts[optnum].val;
8386 }
8387 }
8388
8389 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
8390 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
8391 (curproxy->cap & cfg_opts2[optnum].cap) &&
8392 (curproxy->options2 & cfg_opts2[optnum].val)) {
8393 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8394 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
8395 err_code |= ERR_WARN;
8396 curproxy->options2 &= ~cfg_opts2[optnum].val;
8397 }
8398 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008399
Willy Tarreau29fbe512015-08-20 19:35:14 +02008400#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008401 if (curproxy->conn_src.bind_hdr_occ) {
8402 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008403 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01008404 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008405 err_code |= ERR_WARN;
8406 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008407#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008408 }
8409
Willy Tarreaubaaee002006-06-26 02:48:02 +02008410 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01008411 * ensure that we're not cross-dressing a TCP server into HTTP.
8412 */
8413 newsrv = curproxy->srv;
8414 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01008415 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008416 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
8417 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008418 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01008419 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008420
Willy Tarreau0cec3312011-10-31 13:49:26 +01008421 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
8422 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
8423 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8424 err_code |= ERR_WARN;
8425 }
8426
Willy Tarreauc93cd162014-05-13 15:54:22 +02008427 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02008428 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
8429 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8430 err_code |= ERR_WARN;
8431 }
8432
Willy Tarreau29fbe512015-08-20 19:35:14 +02008433#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008434 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
8435 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008436 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 +01008437 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008438 err_code |= ERR_WARN;
8439 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008440#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01008441 newsrv = newsrv->next;
8442 }
8443
Willy Tarreaue42bd962014-09-16 16:21:19 +02008444 /* check if we have a frontend with "tcp-request content" looking at L7
8445 * with no inspect-delay
8446 */
8447 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
8448 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008449 if (trule->action == ACT_TCP_CAPTURE &&
Thierry FOURNIERd0d65ae2015-08-04 08:21:12 +02008450 !(trule->arg.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008451 break;
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008452 if ((trule->action >= ACT_ACTION_TRK_SC0 && trule->action <= ACT_ACTION_TRK_SCMAX) &&
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008453 !(trule->arg.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008454 break;
8455 }
8456
8457 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
8458 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
8459 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
8460 " This means that these rules will randomly find their contents. This can be fixed by"
8461 " setting the tcp-request inspect-delay.\n",
8462 proxy_type_str(curproxy), curproxy->id);
8463 err_code |= ERR_WARN;
8464 }
8465 }
8466
Willy Tarreauc1a21672009-08-16 22:37:44 +02008467 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02008468 if (!curproxy->accept)
8469 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02008470
Willy Tarreauc1a21672009-08-16 22:37:44 +02008471 if (curproxy->tcp_req.inspect_delay ||
8472 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02008473 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008474
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008475 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008476 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008477 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008478 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008479
8480 /* both TCP and HTTP must check switching rules */
8481 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
8482 }
8483
8484 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02008485 if (curproxy->tcp_req.inspect_delay ||
8486 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
8487 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
8488
Emeric Brun97679e72010-09-23 17:56:44 +02008489 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
8490 curproxy->be_rsp_ana |= AN_RES_INSPECT;
8491
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008492 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008493 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008494 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008495 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008496
8497 /* If the backend does requires RDP cookie persistence, we have to
8498 * enable the corresponding analyser.
8499 */
8500 if (curproxy->options2 & PR_O2_RDPC_PRST)
8501 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
8502 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008503 }
8504
8505 /***********************************************************/
8506 /* At this point, target names have already been resolved. */
8507 /***********************************************************/
8508
8509 /* Check multi-process mode compatibility */
8510
8511 if (global.nbproc > 1 && global.stats_fe) {
8512 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8513 unsigned long mask;
8514
8515 mask = nbits(global.nbproc);
8516 if (global.stats_fe->bind_proc)
8517 mask &= global.stats_fe->bind_proc;
8518
8519 if (bind_conf->bind_proc)
8520 mask &= bind_conf->bind_proc;
8521
8522 /* stop here if more than one process is used */
David Carliere6c39412015-07-02 07:00:17 +00008523 if (my_popcountl(mask) > 1)
Willy Tarreau419ead82014-09-16 13:41:21 +02008524 break;
8525 }
8526 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
8527 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");
8528 }
8529 }
8530
8531 /* Make each frontend inherit bind-process from its listeners when not specified. */
8532 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8533 if (curproxy->bind_proc)
8534 continue;
8535
8536 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8537 unsigned long mask;
8538
Willy Tarreaue428b082015-05-04 21:57:58 +02008539 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008540 curproxy->bind_proc |= mask;
8541 }
8542
8543 if (!curproxy->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008544 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008545 }
8546
8547 if (global.stats_fe) {
8548 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8549 unsigned long mask;
8550
Willy Tarreaue428b082015-05-04 21:57:58 +02008551 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008552 global.stats_fe->bind_proc |= mask;
8553 }
8554 if (!global.stats_fe->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008555 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008556 }
8557
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02008558 /* propagate bindings from frontends to backends. Don't do it if there
8559 * are any fatal errors as we must not call it with unresolved proxies.
8560 */
8561 if (!cfgerr) {
8562 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8563 if (curproxy->cap & PR_CAP_FE)
8564 propagate_processes(curproxy, NULL);
8565 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008566 }
8567
8568 /* Bind each unbound backend to all processes when not specified. */
8569 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8570 if (curproxy->bind_proc)
8571 continue;
Willy Tarreaue428b082015-05-04 21:57:58 +02008572 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008573 }
8574
8575 /*******************************************************/
8576 /* At this step, all proxies have a non-null bind_proc */
8577 /*******************************************************/
8578
8579 /* perform the final checks before creating tasks */
8580
8581 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8582 struct listener *listener;
8583 unsigned int next_id;
8584 int nbproc;
8585
David Carliere6c39412015-07-02 07:00:17 +00008586 nbproc = my_popcountl(curproxy->bind_proc & nbits(global.nbproc));
Willy Tarreauc1a21672009-08-16 22:37:44 +02008587
Emeric Brunc52962f2012-11-15 18:28:02 +01008588#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008589 /* Configure SSL for each bind line.
8590 * Note: if configuration fails at some point, the ->ctx member
8591 * remains NULL so that listeners can later detach.
8592 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008593 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008594 int alloc_ctx;
8595
Emeric Brunc52962f2012-11-15 18:28:02 +01008596 if (!bind_conf->is_ssl) {
8597 if (bind_conf->default_ctx) {
8598 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
8599 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
8600 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008601 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01008602 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008603 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02008604 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008605 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008606 cfgerr++;
8607 continue;
8608 }
8609
Emeric Brun8dc60392014-05-09 13:52:00 +02008610 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008611 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02008612 if (alloc_ctx == SHCTX_E_INIT_LOCK)
8613 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");
8614 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008615 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02008616 cfgerr++;
8617 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008618 }
8619
Emeric Brunfc0421f2012-09-07 17:30:07 +02008620 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008621 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008622
8623 /* initialize CA variables if the certificates generation is enabled */
8624 cfgerr += ssl_sock_load_ca(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008625 }
Emeric Brunc52962f2012-11-15 18:28:02 +01008626#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008627
Willy Tarreaue6b98942007-10-29 01:09:36 +01008628 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008629 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008630 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008631 if (!listener->luid) {
8632 /* listener ID not set, use automatic numbering with first
8633 * spare entry starting with next_luid.
8634 */
8635 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
8636 listener->conf.id.key = listener->luid = next_id;
8637 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008638 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01008639 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008640
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008641 /* enable separate counters */
8642 if (curproxy->options2 & PR_O2_SOCKSTAT) {
8643 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01008644 if (!listener->name)
8645 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008646 }
Willy Tarreau81796be2012-09-22 19:11:47 +02008647
Willy Tarreaue6b98942007-10-29 01:09:36 +01008648 if (curproxy->options & PR_O_TCP_NOLING)
8649 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02008650 if (!listener->maxconn)
8651 listener->maxconn = curproxy->maxconn;
8652 if (!listener->backlog)
8653 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01008654 if (!listener->maxaccept)
8655 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
8656
8657 /* we want to have an optimal behaviour on single process mode to
8658 * maximize the work at once, but in multi-process we want to keep
8659 * some fairness between processes, so we target half of the max
8660 * number of events to be balanced over all the processes the proxy
8661 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
8662 * used to disable the limit.
8663 */
8664 if (listener->maxaccept > 0) {
8665 if (nbproc > 1)
8666 listener->maxaccept = (listener->maxaccept + 1) / 2;
8667 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
8668 }
8669
Willy Tarreau9903f0e2015-04-04 18:50:31 +02008670 listener->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02008671 listener->handler = process_stream;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008672 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01008673 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01008674
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008675 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
8676 listener->options |= LI_O_TCP_RULES;
8677
Willy Tarreaude3041d2010-05-31 10:56:17 +02008678 if (curproxy->mon_mask.s_addr)
8679 listener->options |= LI_O_CHK_MONNET;
8680
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008681 /* smart accept mode is automatic in HTTP mode */
8682 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008683 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008684 !(curproxy->no_options2 & PR_O2_SMARTACC)))
8685 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01008686 }
8687
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008688 /* Release unused SSL configs */
8689 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8690 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008691 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008692#ifdef USE_OPENSSL
Christopher Faulet31af49d2015-06-09 17:29:50 +02008693 ssl_sock_free_ca(bind_conf);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008694 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008695 free(bind_conf->ca_file);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008696 free(bind_conf->ca_sign_file);
8697 free(bind_conf->ca_sign_pass);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008698 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02008699 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008700 free(bind_conf->crl_file);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008701 if(bind_conf->keys_ref) {
8702 free(bind_conf->keys_ref->filename);
8703 free(bind_conf->keys_ref->tlskeys);
8704 free(bind_conf->keys_ref);
8705 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008706#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008707 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008708
Willy Tarreau102df612014-05-07 23:56:38 +02008709 if (nbproc > 1) {
8710 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02008711 int count, maxproc = 0;
8712
8713 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
David Carliere6c39412015-07-02 07:00:17 +00008714 count = my_popcountl(bind_conf->bind_proc);
Willy Tarreaueb791e02014-09-16 15:11:04 +02008715 if (count > maxproc)
8716 maxproc = count;
8717 }
8718 /* backends have 0, frontends have 1 or more */
8719 if (maxproc != 1)
8720 Warning("Proxy '%s': in multi-process mode, stats will be"
8721 " limited to process assigned to the current request.\n",
8722 curproxy->id);
8723
Willy Tarreau102df612014-05-07 23:56:38 +02008724 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
8725 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
8726 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008727 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008728 }
Willy Tarreau102df612014-05-07 23:56:38 +02008729 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
8730 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
8731 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008732 }
8733 }
Willy Tarreau918ff602011-07-25 16:33:49 +02008734
8735 /* create the task associated with the proxy */
8736 curproxy->task = task_new();
8737 if (curproxy->task) {
8738 curproxy->task->context = curproxy;
8739 curproxy->task->process = manage_proxy;
8740 /* no need to queue, it will be done automatically if some
8741 * listener gets limited.
8742 */
8743 curproxy->task->expire = TICK_ETERNITY;
8744 } else {
8745 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
8746 curproxy->id);
8747 cfgerr++;
8748 }
Willy Tarreaub369a042014-09-16 13:21:03 +02008749 }
8750
Willy Tarreaufbb78422011-06-05 15:38:35 +02008751 /* automatically compute fullconn if not set. We must not do it in the
8752 * loop above because cross-references are not yet fully resolved.
8753 */
8754 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8755 /* If <fullconn> is not set, let's set it to 10% of the sum of
8756 * the possible incoming frontend's maxconns.
8757 */
8758 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
8759 struct proxy *fe;
8760 int total = 0;
8761
8762 /* sum up the number of maxconns of frontends which
8763 * reference this backend at least once or which are
8764 * the same one ('listen').
8765 */
8766 for (fe = proxy; fe; fe = fe->next) {
8767 struct switching_rule *rule;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008768 int found = 0;
8769
8770 if (!(fe->cap & PR_CAP_FE))
8771 continue;
8772
8773 if (fe == curproxy) /* we're on a "listen" instance */
8774 found = 1;
8775
8776 if (fe->defbe.be == curproxy) /* "default_backend" */
8777 found = 1;
8778
8779 /* check if a "use_backend" rule matches */
8780 if (!found) {
8781 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01008782 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02008783 found = 1;
8784 break;
8785 }
8786 }
8787 }
8788
Willy Tarreaufbb78422011-06-05 15:38:35 +02008789 /* now we've checked all possible ways to reference a backend
8790 * from a frontend.
8791 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02008792 if (!found)
8793 continue;
8794 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008795 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02008796 /* we have the sum of the maxconns in <total>. We only
8797 * keep 10% of that sum to set the default fullconn, with
8798 * a hard minimum of 1 (to avoid a divide by zero).
8799 */
8800 curproxy->fullconn = (total + 9) / 10;
8801 if (!curproxy->fullconn)
8802 curproxy->fullconn = 1;
8803 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01008804 }
8805
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008806 /*
8807 * Recount currently required checks.
8808 */
8809
8810 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
8811 int optnum;
8812
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008813 for (optnum = 0; cfg_opts[optnum].name; optnum++)
8814 if (curproxy->options & cfg_opts[optnum].val)
8815 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008816
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008817 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
8818 if (curproxy->options2 & cfg_opts2[optnum].val)
8819 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008820 }
8821
Willy Tarreau0fca4832015-05-01 19:12:05 +02008822 /* compute the required process bindings for the peers */
8823 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
8824 if (curproxy->table.peers.p)
8825 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
8826
Willy Tarreau122541c2011-09-07 21:24:49 +02008827 if (peers) {
8828 struct peers *curpeers = peers, **last;
8829 struct peer *p, *pb;
8830
Willy Tarreau1e273012015-05-01 19:15:17 +02008831 /* Remove all peers sections which don't have a valid listener,
8832 * which are not used by any table, or which are bound to more
8833 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02008834 */
8835 last = &peers;
8836 while (*last) {
8837 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008838
8839 if (curpeers->state == PR_STSTOPPED) {
8840 /* the "disabled" keyword was present */
8841 if (curpeers->peers_fe)
8842 stop_proxy(curpeers->peers_fe);
8843 curpeers->peers_fe = NULL;
8844 }
8845 else if (!curpeers->peers_fe) {
8846 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
8847 curpeers->id, localpeer);
8848 }
David Carliere6c39412015-07-02 07:00:17 +00008849 else if (my_popcountl(curpeers->peers_fe->bind_proc) != 1) {
Willy Tarreau1e273012015-05-01 19:15:17 +02008850 /* either it's totally stopped or too much used */
8851 if (curpeers->peers_fe->bind_proc) {
8852 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreau64c57222015-05-04 21:48:51 +02008853 "running in different processes (%d different ones). "
8854 "Check global.nbproc and all tables' bind-process "
David Carliere6c39412015-07-02 07:00:17 +00008855 "settings.\n", curpeers->id, my_popcountl(curpeers->peers_fe->bind_proc));
Willy Tarreau1e273012015-05-01 19:15:17 +02008856 cfgerr++;
8857 }
8858 stop_proxy(curpeers->peers_fe);
8859 curpeers->peers_fe = NULL;
8860 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008861 else {
Emeric Brunb3971ab2015-05-12 18:49:09 +02008862 peers_init_sync(curpeers);
Willy Tarreau122541c2011-09-07 21:24:49 +02008863 last = &curpeers->next;
8864 continue;
8865 }
8866
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008867 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02008868 p = curpeers->remote;
8869 while (p) {
8870 pb = p->next;
8871 free(p->id);
8872 free(p);
8873 p = pb;
8874 }
8875
8876 /* Destroy and unlink this curpeers section.
8877 * Note: curpeers is backed up into *last.
8878 */
8879 free(curpeers->id);
8880 curpeers = curpeers->next;
8881 free(*last);
8882 *last = curpeers;
8883 }
8884 }
8885
Willy Tarreau6866f3f2015-05-01 19:09:08 +02008886 /* initialize stick-tables on backend capable proxies. This must not
8887 * be done earlier because the data size may be discovered while parsing
8888 * other proxies.
8889 */
8890 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8891 if (curproxy->state == PR_STSTOPPED)
8892 continue;
8893
8894 if (!stktable_init(&curproxy->table)) {
8895 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
8896 cfgerr++;
8897 }
8898 }
8899
Simon Horman0d16a402015-01-30 11:22:58 +09008900 if (mailers) {
8901 struct mailers *curmailers = mailers, **last;
8902 struct mailer *m, *mb;
8903
8904 /* Remove all mailers sections which don't have a valid listener.
8905 * This can happen when a mailers section is never referenced.
8906 */
8907 last = &mailers;
8908 while (*last) {
8909 curmailers = *last;
8910 if (curmailers->users) {
8911 last = &curmailers->next;
8912 continue;
8913 }
8914
8915 Warning("Removing incomplete section 'mailers %s'.\n",
8916 curmailers->id);
8917
8918 m = curmailers->mailer_list;
8919 while (m) {
8920 mb = m->next;
8921 free(m->id);
8922 free(m);
8923 m = mb;
8924 }
8925
8926 /* Destroy and unlink this curmailers section.
8927 * Note: curmailers is backed up into *last.
8928 */
8929 free(curmailers->id);
8930 curmailers = curmailers->next;
8931 free(*last);
8932 *last = curmailers;
8933 }
8934 }
8935
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02008936 /* Update server_state_file_name to backend name if backend is supposed to use
8937 * a server-state file locally defined and none has been provided */
8938 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8939 if (curproxy->load_server_state_from_file == PR_SRV_STATE_FILE_LOCAL &&
8940 curproxy->server_state_file_name == NULL)
8941 curproxy->server_state_file_name = strdup(curproxy->id);
8942 }
8943
Willy Tarreau34eb6712011-10-24 18:15:04 +02008944 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02008945 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02008946 MEM_F_SHARED);
8947
Willy Tarreaubb925012009-07-23 13:36:36 +02008948 if (cfgerr > 0)
8949 err_code |= ERR_ALERT | ERR_FATAL;
8950 out:
8951 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02008952}
8953
Willy Tarreau5b2c3362008-07-09 19:39:06 +02008954/*
8955 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
8956 * parsing sessions.
8957 */
8958void cfg_register_keywords(struct cfg_kw_list *kwl)
8959{
8960 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
8961}
Willy Tarreaubaaee002006-06-26 02:48:02 +02008962
Willy Tarreau5b2c3362008-07-09 19:39:06 +02008963/*
8964 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
8965 */
8966void cfg_unregister_keywords(struct cfg_kw_list *kwl)
8967{
8968 LIST_DEL(&kwl->list);
8969 LIST_INIT(&kwl->list);
8970}
Willy Tarreaubaaee002006-06-26 02:48:02 +02008971
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01008972/* this function register new section in the haproxy configuration file.
8973 * <section_name> is the name of this new section and <section_parser>
8974 * is the called parser. If two section declaration have the same name,
8975 * only the first declared is used.
8976 */
8977int cfg_register_section(char *section_name,
8978 int (*section_parser)(const char *, int, char **, int))
8979{
8980 struct cfg_section *cs;
8981
8982 cs = calloc(1, sizeof(*cs));
8983 if (!cs) {
8984 Alert("register section '%s': out of memory.\n", section_name);
8985 return 0;
8986 }
8987
8988 cs->section_name = section_name;
8989 cs->section_parser = section_parser;
8990
8991 LIST_ADDQ(&sections, &cs->list);
8992
8993 return 1;
8994}
8995
Willy Tarreaubaaee002006-06-26 02:48:02 +02008996/*
David Carlier845efb52015-09-25 11:49:18 +01008997 * free all config section entries
8998 */
8999void cfg_unregister_sections(void)
9000{
9001 struct cfg_section *cs, *ics;
9002
9003 list_for_each_entry_safe(cs, ics, &sections, list) {
9004 LIST_DEL(&cs->list);
9005 free(cs);
9006 }
9007}
9008
9009/*
Willy Tarreaubaaee002006-06-26 02:48:02 +02009010 * Local variables:
9011 * c-indent-level: 8
9012 * c-basic-offset: 8
9013 * End:
9014 */