blob: ec47542ca2136871bcc53f84ef4273411b14ebe5 [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
Baptiste Assmann7f43fa92016-01-21 00:59:46 +01002320 if (!port1 && !port2) {
2321 Alert("parsing [%s:%d] : '%s %s' : no UDP port specified\n",
2322 file, linenum, args[0], args[1]);
2323 err_code |= ERR_ALERT | ERR_FATAL;
2324 goto out;
2325 }
2326
Baptiste Assmann325137d2015-04-13 23:40:55 +02002327 newnameserver->addr = *sk;
2328 }
2329 else if (strcmp(args[0], "hold") == 0) { /* hold periods */
2330 const char *res;
2331 unsigned int time;
2332
2333 if (!*args[2]) {
2334 Alert("parsing [%s:%d] : '%s' expects an <event> and a <time> as arguments.\n",
2335 file, linenum, args[0]);
2336 Alert("<event> can be either 'valid', 'nx', 'refused', 'timeout', or 'other'\n");
2337 err_code |= ERR_ALERT | ERR_FATAL;
2338 goto out;
2339 }
2340 res = parse_time_err(args[2], &time, TIME_UNIT_MS);
2341 if (res) {
2342 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2343 file, linenum, *res, args[0]);
2344 err_code |= ERR_ALERT | ERR_FATAL;
2345 goto out;
2346 }
2347 if (strcmp(args[1], "valid") == 0)
2348 curr_resolvers->hold.valid = time;
2349 else {
2350 Alert("parsing [%s:%d] : '%s' unknown <event>: '%s', expects 'valid'\n",
2351 file, linenum, args[0], args[1]);
2352 err_code |= ERR_ALERT | ERR_FATAL;
2353 goto out;
2354 }
2355
2356 }
2357 else if (strcmp(args[0], "resolve_retries") == 0) {
2358 if (!*args[1]) {
2359 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2360 file, linenum, args[0]);
2361 err_code |= ERR_ALERT | ERR_FATAL;
2362 goto out;
2363 }
2364 curr_resolvers->resolve_retries = atoi(args[1]);
2365 }
2366 else if (strcmp(args[0], "timeout") == 0) {
2367 const char *res;
2368 unsigned int timeout_retry;
2369
2370 if (!*args[2]) {
2371 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments.\n",
2372 file, linenum, args[0]);
2373 err_code |= ERR_ALERT | ERR_FATAL;
2374 goto out;
2375 }
2376 res = parse_time_err(args[2], &timeout_retry, TIME_UNIT_MS);
2377 if (res) {
2378 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2379 file, linenum, *res, args[0]);
2380 err_code |= ERR_ALERT | ERR_FATAL;
2381 goto out;
2382 }
2383 curr_resolvers->timeout.retry = timeout_retry;
2384 } /* neither "nameserver" nor "resolvers" */
2385 else if (*args[0] != 0) {
2386 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2387 err_code |= ERR_ALERT | ERR_FATAL;
2388 goto out;
2389 }
2390
2391 out:
2392 free(errmsg);
2393 return err_code;
2394}
Simon Horman0d16a402015-01-30 11:22:58 +09002395
2396/*
William Lallemand51097192015-04-14 16:35:22 +02002397 * Parse a line in a <listen>, <frontend> or <backend> section.
Simon Horman0d16a402015-01-30 11:22:58 +09002398 * Returns the error code, 0 if OK, or any combination of :
2399 * - ERR_ABORT: must abort ASAP
2400 * - ERR_FATAL: we can continue parsing but not start the service
2401 * - ERR_WARN: a warning has been emitted
2402 * - ERR_ALERT: an alert has been emitted
2403 * Only the two first ones can stop processing, the two others are just
2404 * indicators.
2405 */
2406int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
2407{
2408 static struct mailers *curmailers = NULL;
2409 struct mailer *newmailer = NULL;
2410 const char *err;
2411 int err_code = 0;
2412 char *errmsg = NULL;
2413
2414 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
2415 if (!*args[1]) {
2416 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
2417 err_code |= ERR_ALERT | ERR_ABORT;
2418 goto out;
2419 }
2420
2421 err = invalid_char(args[1]);
2422 if (err) {
2423 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2424 file, linenum, *err, args[0], args[1]);
2425 err_code |= ERR_ALERT | ERR_ABORT;
2426 goto out;
2427 }
2428
2429 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
2430 /*
2431 * If there are two proxies with the same name only following
2432 * combinations are allowed:
2433 */
2434 if (strcmp(curmailers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002435 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 +09002436 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002437 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman0d16a402015-01-30 11:22:58 +09002438 }
2439 }
2440
2441 if ((curmailers = (struct mailers *)calloc(1, sizeof(struct mailers))) == NULL) {
2442 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2443 err_code |= ERR_ALERT | ERR_ABORT;
2444 goto out;
2445 }
2446
2447 curmailers->next = mailers;
2448 mailers = curmailers;
2449 curmailers->conf.file = strdup(file);
2450 curmailers->conf.line = linenum;
2451 curmailers->id = strdup(args[1]);
2452 }
2453 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
2454 struct sockaddr_storage *sk;
2455 int port1, port2;
2456 struct protocol *proto;
2457
2458 if (!*args[2]) {
2459 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2460 file, linenum, args[0]);
2461 err_code |= ERR_ALERT | ERR_FATAL;
2462 goto out;
2463 }
2464
2465 err = invalid_char(args[1]);
2466 if (err) {
2467 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2468 file, linenum, *err, args[1]);
2469 err_code |= ERR_ALERT | ERR_FATAL;
2470 goto out;
2471 }
2472
2473 if ((newmailer = (struct mailer *)calloc(1, sizeof(struct mailer))) == NULL) {
2474 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2475 err_code |= ERR_ALERT | ERR_ABORT;
2476 goto out;
2477 }
2478
2479 /* the mailers are linked backwards first */
2480 curmailers->count++;
2481 newmailer->next = curmailers->mailer_list;
2482 curmailers->mailer_list = newmailer;
2483 newmailer->mailers = curmailers;
2484 newmailer->conf.file = strdup(file);
2485 newmailer->conf.line = linenum;
2486
2487 newmailer->id = strdup(args[1]);
2488
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002489 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Simon Horman0d16a402015-01-30 11:22:58 +09002490 if (!sk) {
2491 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2492 err_code |= ERR_ALERT | ERR_FATAL;
2493 goto out;
2494 }
2495
2496 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002497 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2498 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002499 file, linenum, args[0], args[1]);
2500 err_code |= ERR_ALERT | ERR_FATAL;
2501 goto out;
2502 }
2503
2504 if (port1 != port2) {
2505 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed 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 if (!port1) {
2512 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2513 file, linenum, args[0], args[1], args[2]);
2514 err_code |= ERR_ALERT | ERR_FATAL;
2515 goto out;
2516 }
2517
2518 newmailer->addr = *sk;
2519 newmailer->proto = proto;
2520 newmailer->xprt = &raw_sock;
2521 newmailer->sock_init_arg = NULL;
2522 } /* neither "mailer" nor "mailers" */
2523 else if (*args[0] != 0) {
2524 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2525 err_code |= ERR_ALERT | ERR_FATAL;
2526 goto out;
2527 }
2528
2529out:
2530 free(errmsg);
2531 return err_code;
2532}
2533
Simon Horman9dc49962015-01-30 11:22:59 +09002534static void free_email_alert(struct proxy *p)
2535{
2536 free(p->email_alert.mailers.name);
2537 p->email_alert.mailers.name = NULL;
2538 free(p->email_alert.from);
2539 p->email_alert.from = NULL;
2540 free(p->email_alert.to);
2541 p->email_alert.to = NULL;
2542 free(p->email_alert.myhostname);
2543 p->email_alert.myhostname = NULL;
2544}
2545
Willy Tarreau3842f002009-06-14 11:39:52 +02002546int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002547{
2548 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002549 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002550 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002551 int rc;
2552 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002553 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002554 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002555 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002556 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002557 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002558
Willy Tarreau977b8e42006-12-29 14:19:17 +01002559 if (!strcmp(args[0], "listen"))
2560 rc = PR_CAP_LISTEN;
2561 else if (!strcmp(args[0], "frontend"))
2562 rc = PR_CAP_FE | PR_CAP_RS;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02002563 else if (!strcmp(args[0], "backend"))
Willy Tarreau977b8e42006-12-29 14:19:17 +01002564 rc = PR_CAP_BE | PR_CAP_RS;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002565 else
2566 rc = PR_CAP_NONE;
2567
2568 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002569 if (!*args[1]) {
2570 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
2571 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
2572 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002573 err_code |= ERR_ALERT | ERR_ABORT;
2574 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002575 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002576
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002577 err = invalid_char(args[1]);
2578 if (err) {
2579 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2580 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002581 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002582 }
2583
Willy Tarreau8f50b682015-05-26 11:45:02 +02002584 curproxy = (rc & PR_CAP_FE) ? proxy_fe_by_name(args[1]) : proxy_be_by_name(args[1]);
2585 if (curproxy) {
2586 Alert("Parsing [%s:%d]: %s '%s' has the same name as %s '%s' declared at %s:%d.\n",
2587 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2588 curproxy->id, curproxy->conf.file, curproxy->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002589 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002590 }
2591
Willy Tarreaubaaee002006-06-26 02:48:02 +02002592 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
2593 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002594 err_code |= ERR_ALERT | ERR_ABORT;
2595 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002596 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002597
Willy Tarreau97cb7802010-01-03 20:23:58 +01002598 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002599 curproxy->next = proxy;
2600 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002601 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2602 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002603 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002604 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002605 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002606 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002607
William Lallemand6e62fb62015-04-28 16:55:23 +02002608 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2609 if (curproxy->cap & PR_CAP_FE)
2610 Alert("parsing [%s:%d] : please use the 'bind' keyword for listening addresses.\n", file, linenum);
2611 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002612 }
2613
2614 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002615 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002616 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002617
Willy Tarreaubaaee002006-06-26 02:48:02 +02002618 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002619 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002620 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002621 curproxy->no_options = defproxy.no_options;
2622 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002623 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002624 curproxy->except_net = defproxy.except_net;
2625 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002626 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002627 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002628
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002629 if (defproxy.fwdfor_hdr_len) {
2630 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2631 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2632 }
2633
Willy Tarreaub86db342009-11-30 11:50:16 +01002634 if (defproxy.orgto_hdr_len) {
2635 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2636 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2637 }
2638
Mark Lamourinec2247f02012-01-04 13:02:01 -05002639 if (defproxy.server_id_hdr_len) {
2640 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2641 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2642 }
2643
Willy Tarreau977b8e42006-12-29 14:19:17 +01002644 if (curproxy->cap & PR_CAP_FE) {
2645 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002646 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002647 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002648
2649 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002650 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2651 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002652
2653 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2654 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002655
Willy Tarreau977b8e42006-12-29 14:19:17 +01002656 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002657 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002658 curproxy->fullconn = defproxy.fullconn;
2659 curproxy->conn_retries = defproxy.conn_retries;
Joseph Lynch726ab712015-05-11 23:25:34 -07002660 curproxy->redispatch_after = defproxy.redispatch_after;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002661 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002662
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002663 if (defproxy.check_req) {
2664 curproxy->check_req = calloc(1, defproxy.check_len);
2665 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2666 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002667 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002668
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002669 if (defproxy.expect_str) {
2670 curproxy->expect_str = strdup(defproxy.expect_str);
2671 if (defproxy.expect_regex) {
2672 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002673 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2674 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002675 }
2676 }
2677
Willy Tarreau67402132012-05-31 20:40:20 +02002678 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002679 if (defproxy.cookie_name)
2680 curproxy->cookie_name = strdup(defproxy.cookie_name);
2681 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002682 if (defproxy.cookie_domain)
2683 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002684
Willy Tarreau31936852010-10-06 16:59:56 +02002685 if (defproxy.cookie_maxidle)
2686 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2687
2688 if (defproxy.cookie_maxlife)
2689 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2690
Emeric Brun647caf12009-06-30 17:57:00 +02002691 if (defproxy.rdp_cookie_name)
2692 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2693 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2694
Willy Tarreau01732802007-11-01 22:48:15 +01002695 if (defproxy.url_param_name)
2696 curproxy->url_param_name = strdup(defproxy.url_param_name);
2697 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002698
Benoitaffb4812009-03-25 13:02:10 +01002699 if (defproxy.hh_name)
2700 curproxy->hh_name = strdup(defproxy.hh_name);
2701 curproxy->hh_len = defproxy.hh_len;
2702 curproxy->hh_match_domain = defproxy.hh_match_domain;
2703
Willy Tarreauef9a3602012-12-08 22:29:20 +01002704 if (defproxy.conn_src.iface_name)
2705 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2706 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002707 curproxy->conn_src.opts = defproxy.conn_src.opts;
Willy Tarreau29fbe512015-08-20 19:35:14 +02002708#if defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002709 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002710#endif
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02002711 curproxy->load_server_state_from_file = defproxy.load_server_state_from_file;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002712 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002713
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002714 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002715 if (defproxy.capture_name)
2716 curproxy->capture_name = strdup(defproxy.capture_name);
2717 curproxy->capture_namelen = defproxy.capture_namelen;
2718 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002719 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002720
Willy Tarreau977b8e42006-12-29 14:19:17 +01002721 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002722 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002723 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002724 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002725 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002726 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002727 curproxy->mon_net = defproxy.mon_net;
2728 curproxy->mon_mask = defproxy.mon_mask;
2729 if (defproxy.monitor_uri)
2730 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2731 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002732 if (defproxy.defbe.name)
2733 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002734
2735 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002736 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2737 if (curproxy->conf.logformat_string &&
2738 curproxy->conf.logformat_string != default_http_log_format &&
2739 curproxy->conf.logformat_string != default_tcp_log_format &&
2740 curproxy->conf.logformat_string != clf_http_log_format)
2741 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2742
2743 if (defproxy.conf.lfs_file) {
2744 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2745 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2746 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002747
2748 /* get either a pointer to the logformat string for RFC5424 structured-data or a copy of it */
2749 curproxy->conf.logformat_sd_string = defproxy.conf.logformat_sd_string;
2750 if (curproxy->conf.logformat_sd_string &&
2751 curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
2752 curproxy->conf.logformat_sd_string = strdup(curproxy->conf.logformat_sd_string);
2753
2754 if (defproxy.conf.lfsd_file) {
2755 curproxy->conf.lfsd_file = strdup(defproxy.conf.lfsd_file);
2756 curproxy->conf.lfsd_line = defproxy.conf.lfsd_line;
2757 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002758 }
2759
2760 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002761 curproxy->timeout.connect = defproxy.timeout.connect;
2762 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002763 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002764 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002765 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002766 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002767 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002768 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002769 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002770 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002771 }
2772
Willy Tarreaubaaee002006-06-26 02:48:02 +02002773 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002774 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002775
2776 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002777 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002778 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002779 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002780 LIST_INIT(&node->list);
2781 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2782 }
2783
Willy Tarreau62a61232013-04-12 18:13:46 +02002784 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2785 if (curproxy->conf.uniqueid_format_string)
2786 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2787
Dragan Dosen43885c72015-10-01 13:18:13 +02002788 chunk_dup(&curproxy->log_tag, &defproxy.log_tag);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002789
Willy Tarreau62a61232013-04-12 18:13:46 +02002790 if (defproxy.conf.uif_file) {
2791 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2792 curproxy->conf.uif_line = defproxy.conf.uif_line;
2793 }
William Lallemanda73203e2012-03-12 12:48:57 +01002794
2795 /* copy default header unique id */
2796 if (defproxy.header_unique_id)
2797 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2798
William Lallemand82fe75c2012-10-23 10:25:10 +02002799 /* default compression options */
2800 if (defproxy.comp != NULL) {
2801 curproxy->comp = calloc(1, sizeof(struct comp));
2802 curproxy->comp->algos = defproxy.comp->algos;
2803 curproxy->comp->types = defproxy.comp->types;
2804 }
2805
Willy Tarreaubaaee002006-06-26 02:48:02 +02002806 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002807 curproxy->conf.used_listener_id = EB_ROOT;
2808 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002809
Simon Horman98637e52014-06-20 12:30:16 +09002810 if (defproxy.check_path)
2811 curproxy->check_path = strdup(defproxy.check_path);
2812 if (defproxy.check_command)
2813 curproxy->check_command = strdup(defproxy.check_command);
2814
Simon Horman9dc49962015-01-30 11:22:59 +09002815 if (defproxy.email_alert.mailers.name)
2816 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2817 if (defproxy.email_alert.from)
2818 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2819 if (defproxy.email_alert.to)
2820 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2821 if (defproxy.email_alert.myhostname)
2822 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09002823 curproxy->email_alert.level = defproxy.email_alert.level;
Cyril Bonté7e084702015-12-04 03:07:06 +01002824 curproxy->email_alert.set = defproxy.email_alert.set;
Simon Horman9dc49962015-01-30 11:22:59 +09002825
Willy Tarreau93893792009-07-23 13:19:11 +02002826 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002827 }
2828 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2829 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002830 /* FIXME-20070101: we should do this too at the end of the
2831 * config parsing to free all default values.
2832 */
William Lallemand6e62fb62015-04-28 16:55:23 +02002833 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2834 err_code |= ERR_ABORT;
2835 goto out;
2836 }
2837
Willy Tarreaua534fea2008-08-03 12:19:50 +02002838 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002839 free(defproxy.check_command);
2840 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002841 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002842 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002843 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002844 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002845 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002846 free(defproxy.capture_name);
2847 free(defproxy.monitor_uri);
2848 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002849 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002850 free(defproxy.fwdfor_hdr_name);
2851 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002852 free(defproxy.orgto_hdr_name);
2853 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002854 free(defproxy.server_id_hdr_name);
2855 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002856 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002857 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002858 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002859 free(defproxy.expect_regex);
2860 defproxy.expect_regex = NULL;
2861 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002862
Willy Tarreau62a61232013-04-12 18:13:46 +02002863 if (defproxy.conf.logformat_string != default_http_log_format &&
2864 defproxy.conf.logformat_string != default_tcp_log_format &&
2865 defproxy.conf.logformat_string != clf_http_log_format)
2866 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002867
Willy Tarreau62a61232013-04-12 18:13:46 +02002868 free(defproxy.conf.uniqueid_format_string);
2869 free(defproxy.conf.lfs_file);
2870 free(defproxy.conf.uif_file);
Dragan Dosen43885c72015-10-01 13:18:13 +02002871 chunk_destroy(&defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09002872 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02002873
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002874 if (defproxy.conf.logformat_sd_string != default_rfc5424_sd_log_format)
2875 free(defproxy.conf.logformat_sd_string);
2876 free(defproxy.conf.lfsd_file);
2877
Willy Tarreaua534fea2008-08-03 12:19:50 +02002878 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002879 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002880
Willy Tarreaubaaee002006-06-26 02:48:02 +02002881 /* we cannot free uri_auth because it might already be used */
2882 init_default_instance();
2883 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002884 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2885 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002886 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002887 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002888 }
2889 else if (curproxy == NULL) {
2890 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002891 err_code |= ERR_ALERT | ERR_FATAL;
2892 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002893 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002894
2895 /* update the current file and line being parsed */
2896 curproxy->conf.args.file = curproxy->conf.file;
2897 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002898
2899 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002900 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2901 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2902 if (err_code & ERR_FATAL)
2903 goto out;
2904 }
2905 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002906 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002907 int cur_arg;
2908
Willy Tarreaubaaee002006-06-26 02:48:02 +02002909 if (curproxy == &defproxy) {
2910 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002911 err_code |= ERR_ALERT | ERR_FATAL;
2912 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002913 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002914 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002915 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002916
Willy Tarreau24709282013-03-10 21:32:12 +01002917 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002918 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002919 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002920 err_code |= ERR_ALERT | ERR_FATAL;
2921 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002922 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002923
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002924 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002925
2926 /* use default settings for unix sockets */
2927 bind_conf->ux.uid = global.unix_bind.ux.uid;
2928 bind_conf->ux.gid = global.unix_bind.ux.gid;
2929 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002930
2931 /* NOTE: the following line might create several listeners if there
2932 * are comma-separated IPs or port ranges. So all further processing
2933 * will have to be applied to all listeners created after last_listen.
2934 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002935 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2936 if (errmsg && *errmsg) {
2937 indent_msg(&errmsg, 2);
2938 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002939 }
2940 else
2941 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2942 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002943 err_code |= ERR_ALERT | ERR_FATAL;
2944 goto out;
2945 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002946
Willy Tarreau4348fad2012-09-20 16:48:07 +02002947 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2948 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002949 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002950 }
2951
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002952 cur_arg = 2;
2953 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002954 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002955 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002956 char *err;
2957
Willy Tarreau26982662012-09-12 23:17:10 +02002958 kw = bind_find_kw(args[cur_arg]);
2959 if (kw) {
2960 char *err = NULL;
2961 int code;
2962
2963 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002964 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2965 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002966 cur_arg += 1 + kw->skip ;
2967 err_code |= ERR_ALERT | ERR_FATAL;
2968 goto out;
2969 }
2970
Willy Tarreau4348fad2012-09-20 16:48:07 +02002971 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002972 err_code |= code;
2973
2974 if (code) {
2975 if (err && *err) {
2976 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002977 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002978 }
2979 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002980 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2981 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002982 if (code & ERR_FATAL) {
2983 free(err);
2984 cur_arg += 1 + kw->skip;
2985 goto out;
2986 }
2987 }
2988 free(err);
2989 cur_arg += 1 + kw->skip;
2990 continue;
2991 }
2992
Willy Tarreau8638f482012-09-18 18:01:17 +02002993 err = NULL;
2994 if (!bind_dumped) {
2995 bind_dump_kws(&err);
2996 indent_msg(&err, 4);
2997 bind_dumped = 1;
2998 }
2999
3000 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
3001 file, linenum, args[0], args[1], args[cur_arg],
3002 err ? " Registered keywords :" : "", err ? err : "");
3003 free(err);
3004
Willy Tarreau93893792009-07-23 13:19:11 +02003005 err_code |= ERR_ALERT | ERR_FATAL;
3006 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01003007 }
Willy Tarreau93893792009-07-23 13:19:11 +02003008 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003009 }
3010 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01003011 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003012 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
3013 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003014 err_code |= ERR_ALERT | ERR_FATAL;
3015 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003016 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003017 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003018 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003019
Willy Tarreaubaaee002006-06-26 02:48:02 +02003020 /* flush useless bits */
3021 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02003022 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003023 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02003024 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003025 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003026 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003027
William Lallemanddf1425a2015-04-28 20:17:49 +02003028 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3029 goto out;
3030
Willy Tarreau1c47f852006-07-09 08:22:27 +02003031 if (!*args[1]) {
3032 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
3033 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003034 err_code |= ERR_ALERT | ERR_FATAL;
3035 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003036 }
3037
Willy Tarreaua534fea2008-08-03 12:19:50 +02003038 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003039 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02003040 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003041 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02003042 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
3043
Willy Tarreau93893792009-07-23 13:19:11 +02003044 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003045 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003046 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
William Lallemanddf1425a2015-04-28 20:17:49 +02003047 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3048 goto out;
3049
Willy Tarreaubaaee002006-06-26 02:48:02 +02003050 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
3051 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
3052 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
3053 else {
3054 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003055 err_code |= ERR_ALERT | ERR_FATAL;
3056 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003057 }
3058 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003059 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003060 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003061
3062 if (curproxy == &defproxy) {
3063 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3064 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003065 err_code |= ERR_ALERT | ERR_FATAL;
3066 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003067 }
3068
William Lallemanddf1425a2015-04-28 20:17:49 +02003069 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3070 goto out;
3071
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003072 if (!*args[1]) {
3073 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3074 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003075 err_code |= ERR_ALERT | ERR_FATAL;
3076 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003077 }
3078
3079 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003080 curproxy->conf.id.key = curproxy->uuid;
Willy Tarreau0d1fdf72015-05-27 16:44:02 +02003081 curproxy->options |= PR_O_FORCED_ID;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003082
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003083 if (curproxy->uuid <= 0) {
3084 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003085 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003086 err_code |= ERR_ALERT | ERR_FATAL;
3087 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003088 }
3089
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003090 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
3091 if (node) {
3092 struct proxy *target = container_of(node, struct proxy, conf.id);
3093 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
3094 file, linenum, proxy_type_str(curproxy), curproxy->id,
3095 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
3096 err_code |= ERR_ALERT | ERR_FATAL;
3097 goto out;
3098 }
3099 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003100 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003101 else if (!strcmp(args[0], "description")) {
3102 int i, len=0;
3103 char *d;
3104
Cyril Bonté99ed3272010-01-24 23:29:44 +01003105 if (curproxy == &defproxy) {
3106 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3107 file, linenum, args[0]);
3108 err_code |= ERR_ALERT | ERR_FATAL;
3109 goto out;
3110 }
3111
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003112 if (!*args[1]) {
3113 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
3114 file, linenum, args[0]);
3115 return -1;
3116 }
3117
Willy Tarreau348acfe2014-04-14 15:00:39 +02003118 for (i = 1; *args[i]; i++)
3119 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003120
3121 d = (char *)calloc(1, len);
3122 curproxy->desc = d;
3123
Willy Tarreau348acfe2014-04-14 15:00:39 +02003124 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
3125 for (i = 2; *args[i]; i++)
3126 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003127
3128 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003129 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
William Lallemanddf1425a2015-04-28 20:17:49 +02003130 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3131 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003132 curproxy->state = PR_STSTOPPED;
3133 }
3134 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
William Lallemanddf1425a2015-04-28 20:17:49 +02003135 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3136 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003137 curproxy->state = PR_STNEW;
3138 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003139 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
3140 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003141 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003142
3143 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003144 unsigned int low, high;
3145
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003146 if (strcmp(args[cur_arg], "all") == 0) {
3147 set = 0;
3148 break;
3149 }
3150 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003151 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003152 }
3153 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003154 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003155 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01003156 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003157 char *dash = strchr(args[cur_arg], '-');
3158
3159 low = high = str2uic(args[cur_arg]);
3160 if (dash)
3161 high = str2uic(dash + 1);
3162
3163 if (high < low) {
3164 unsigned int swap = low;
3165 low = high;
3166 high = swap;
3167 }
3168
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003169 if (low < 1 || high > LONGBITS) {
3170 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
3171 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02003172 err_code |= ERR_ALERT | ERR_FATAL;
3173 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003174 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01003175 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003176 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003177 }
3178 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003179 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
3180 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003181 err_code |= ERR_ALERT | ERR_FATAL;
3182 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003183 }
3184 cur_arg++;
3185 }
3186 curproxy->bind_proc = set;
3187 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003188 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02003189 if (curproxy == &defproxy) {
3190 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003191 err_code |= ERR_ALERT | ERR_FATAL;
3192 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003193 }
3194
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003195 err = invalid_char(args[1]);
3196 if (err) {
3197 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
3198 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003199 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003200 }
3201
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01003202 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003203 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
3204 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003205 err_code |= ERR_ALERT | ERR_FATAL;
3206 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003207 }
3208 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003209 else if (!strcmp(args[0], "cookie")) { /* cookie name */
3210 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003211
Willy Tarreau977b8e42006-12-29 14:19:17 +01003212 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003213 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003214
Willy Tarreaubaaee002006-06-26 02:48:02 +02003215 if (*(args[1]) == 0) {
3216 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
3217 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003218 err_code |= ERR_ALERT | ERR_FATAL;
3219 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003220 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003221
Willy Tarreau67402132012-05-31 20:40:20 +02003222 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003223 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01003224 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003225 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003226 curproxy->cookie_name = strdup(args[1]);
3227 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003228
Willy Tarreaubaaee002006-06-26 02:48:02 +02003229 cur_arg = 2;
3230 while (*(args[cur_arg])) {
3231 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003232 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003233 }
3234 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003235 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003236 }
3237 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003238 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003239 }
3240 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003241 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003242 }
3243 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003244 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003245 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003246 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003247 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003248 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003249 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003250 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003251 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02003252 else if (!strcmp(args[cur_arg], "httponly")) {
3253 curproxy->ck_opts |= PR_CK_HTTPONLY;
3254 }
3255 else if (!strcmp(args[cur_arg], "secure")) {
3256 curproxy->ck_opts |= PR_CK_SECURE;
3257 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003258 else if (!strcmp(args[cur_arg], "domain")) {
3259 if (!*args[cur_arg + 1]) {
3260 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
3261 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003262 err_code |= ERR_ALERT | ERR_FATAL;
3263 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003264 }
3265
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003266 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003267 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003268 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
3269 " dots nor does not start with a dot."
3270 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003271 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003272 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003273 }
3274
3275 err = invalid_domainchar(args[cur_arg + 1]);
3276 if (err) {
3277 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
3278 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003279 err_code |= ERR_ALERT | ERR_FATAL;
3280 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003281 }
3282
Willy Tarreau68a897b2009-12-03 23:28:34 +01003283 if (!curproxy->cookie_domain) {
3284 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
3285 } else {
3286 /* one domain was already specified, add another one by
3287 * building the string which will be returned along with
3288 * the cookie.
3289 */
3290 char *new_ptr;
3291 int new_len = strlen(curproxy->cookie_domain) +
3292 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
3293 new_ptr = malloc(new_len);
3294 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
3295 free(curproxy->cookie_domain);
3296 curproxy->cookie_domain = new_ptr;
3297 }
Willy Tarreau31936852010-10-06 16:59:56 +02003298 cur_arg++;
3299 }
3300 else if (!strcmp(args[cur_arg], "maxidle")) {
3301 unsigned int maxidle;
3302 const char *res;
3303
3304 if (!*args[cur_arg + 1]) {
3305 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
3306 file, linenum, args[cur_arg]);
3307 err_code |= ERR_ALERT | ERR_FATAL;
3308 goto out;
3309 }
3310
3311 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
3312 if (res) {
3313 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3314 file, linenum, *res, args[cur_arg]);
3315 err_code |= ERR_ALERT | ERR_FATAL;
3316 goto out;
3317 }
3318 curproxy->cookie_maxidle = maxidle;
3319 cur_arg++;
3320 }
3321 else if (!strcmp(args[cur_arg], "maxlife")) {
3322 unsigned int maxlife;
3323 const char *res;
3324
3325 if (!*args[cur_arg + 1]) {
3326 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
3327 file, linenum, args[cur_arg]);
3328 err_code |= ERR_ALERT | ERR_FATAL;
3329 goto out;
3330 }
3331
3332 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
3333 if (res) {
3334 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3335 file, linenum, *res, args[cur_arg]);
3336 err_code |= ERR_ALERT | ERR_FATAL;
3337 goto out;
3338 }
3339 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003340 cur_arg++;
3341 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003342 else {
Willy Tarreau31936852010-10-06 16:59:56 +02003343 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 +02003344 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003345 err_code |= ERR_ALERT | ERR_FATAL;
3346 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003347 }
3348 cur_arg++;
3349 }
Willy Tarreau67402132012-05-31 20:40:20 +02003350 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003351 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
3352 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003353 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003354 }
3355
Willy Tarreau67402132012-05-31 20:40:20 +02003356 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003357 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
3358 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003359 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003360 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003361
Willy Tarreau67402132012-05-31 20:40:20 +02003362 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003363 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
3364 file, linenum);
3365 err_code |= ERR_ALERT | ERR_FATAL;
3366 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003367 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09003368 else if (!strcmp(args[0], "email-alert")) {
3369 if (*(args[1]) == 0) {
3370 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3371 file, linenum, args[0]);
3372 err_code |= ERR_ALERT | ERR_FATAL;
3373 goto out;
3374 }
3375
3376 if (!strcmp(args[1], "from")) {
3377 if (*(args[1]) == 0) {
3378 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3379 file, linenum, args[1]);
3380 err_code |= ERR_ALERT | ERR_FATAL;
3381 goto out;
3382 }
3383 free(curproxy->email_alert.from);
3384 curproxy->email_alert.from = strdup(args[2]);
3385 }
3386 else if (!strcmp(args[1], "mailers")) {
3387 if (*(args[1]) == 0) {
3388 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3389 file, linenum, args[1]);
3390 err_code |= ERR_ALERT | ERR_FATAL;
3391 goto out;
3392 }
3393 free(curproxy->email_alert.mailers.name);
3394 curproxy->email_alert.mailers.name = strdup(args[2]);
3395 }
3396 else if (!strcmp(args[1], "myhostname")) {
3397 if (*(args[1]) == 0) {
3398 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3399 file, linenum, args[1]);
3400 err_code |= ERR_ALERT | ERR_FATAL;
3401 goto out;
3402 }
3403 free(curproxy->email_alert.myhostname);
3404 curproxy->email_alert.myhostname = strdup(args[2]);
3405 }
Simon Horman64e34162015-02-06 11:11:57 +09003406 else if (!strcmp(args[1], "level")) {
3407 curproxy->email_alert.level = get_log_level(args[2]);
3408 if (curproxy->email_alert.level < 0) {
3409 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
3410 file, linenum, args[1], args[2]);
3411 err_code |= ERR_ALERT | ERR_FATAL;
3412 goto out;
3413 }
3414 }
Simon Horman9dc49962015-01-30 11:22:59 +09003415 else if (!strcmp(args[1], "to")) {
3416 if (*(args[1]) == 0) {
3417 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3418 file, linenum, args[1]);
3419 err_code |= ERR_ALERT | ERR_FATAL;
3420 goto out;
3421 }
3422 free(curproxy->email_alert.to);
3423 curproxy->email_alert.to = strdup(args[2]);
3424 }
3425 else {
3426 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
3427 file, linenum, args[1]);
3428 err_code |= ERR_ALERT | ERR_FATAL;
3429 goto out;
3430 }
Simon Horman64e34162015-02-06 11:11:57 +09003431 /* Indicate that the email_alert is at least partially configured */
3432 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09003433 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09003434 else if (!strcmp(args[0], "external-check")) {
3435 if (*(args[1]) == 0) {
3436 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3437 file, linenum, args[0]);
3438 err_code |= ERR_ALERT | ERR_FATAL;
3439 goto out;
3440 }
3441
3442 if (!strcmp(args[1], "command")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003443 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003444 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003445 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003446 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3447 file, linenum, args[1]);
3448 err_code |= ERR_ALERT | ERR_FATAL;
3449 goto out;
3450 }
3451 free(curproxy->check_command);
3452 curproxy->check_command = strdup(args[2]);
3453 }
3454 else if (!strcmp(args[1], "path")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003455 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003456 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003457 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003458 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3459 file, linenum, args[1]);
3460 err_code |= ERR_ALERT | ERR_FATAL;
3461 goto out;
3462 }
3463 free(curproxy->check_path);
3464 curproxy->check_path = strdup(args[2]);
3465 }
3466 else {
3467 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
3468 file, linenum, args[1]);
3469 err_code |= ERR_ALERT | ERR_FATAL;
3470 goto out;
3471 }
3472 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02003473 else if (!strcmp(args[0], "persist")) { /* persist */
3474 if (*(args[1]) == 0) {
3475 Alert("parsing [%s:%d] : missing persist method.\n",
3476 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003477 err_code |= ERR_ALERT | ERR_FATAL;
3478 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003479 }
3480
3481 if (!strncmp(args[1], "rdp-cookie", 10)) {
3482 curproxy->options2 |= PR_O2_RDPC_PRST;
3483
Emeric Brunb982a3d2010-01-04 15:45:53 +01003484 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003485 const char *beg, *end;
3486
3487 beg = args[1] + 11;
3488 end = strchr(beg, ')');
3489
William Lallemanddf1425a2015-04-28 20:17:49 +02003490 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3491 goto out;
3492
Emeric Brun647caf12009-06-30 17:57:00 +02003493 if (!end || end == beg) {
3494 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3495 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003496 err_code |= ERR_ALERT | ERR_FATAL;
3497 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003498 }
3499
3500 free(curproxy->rdp_cookie_name);
3501 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3502 curproxy->rdp_cookie_len = end-beg;
3503 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003504 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003505 free(curproxy->rdp_cookie_name);
3506 curproxy->rdp_cookie_name = strdup("msts");
3507 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3508 }
3509 else { /* syntax */
3510 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\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 }
3516 else {
3517 Alert("parsing [%s:%d] : unknown persist method.\n",
3518 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003519 err_code |= ERR_ALERT | ERR_FATAL;
3520 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003521 }
3522 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003523 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreau6db62c52015-08-10 19:04:29 +02003524 Alert("parsing [%s:%d] : '%s' is not supported anymore, please check the documentation.\n", file, linenum, args[0]);
3525 err_code |= ERR_ALERT | ERR_FATAL;
3526 goto out;
3527 }
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02003528 else if (!strcmp(args[0], "load-server-state-from-file")) {
3529 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3530 err_code |= ERR_WARN;
3531 if (!strcmp(args[1], "global")) { /* use the file pointed to by global server-state-file directive */
3532 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_GLOBAL;
3533 }
3534 else if (!strcmp(args[1], "local")) { /* use the server-state-file-name variable to locate the server-state file */
3535 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_LOCAL;
3536 }
3537 else if (!strcmp(args[1], "none")) { /* don't use server-state-file directive for this backend */
3538 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
3539 }
3540 else {
3541 Alert("parsing [%s:%d] : '%s' expects 'global', 'local' or 'none'. Got '%s'\n",
3542 file, linenum, args[0], args[1]);
3543 err_code |= ERR_ALERT | ERR_FATAL;
3544 goto out;
3545 }
3546 }
3547 else if (!strcmp(args[0], "server-state-file-name")) {
3548 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3549 err_code |= ERR_WARN;
3550 if (*(args[1]) == 0) {
3551 Alert("parsing [%s:%d] : '%s' expects 'use-backend-name' or a string. Got no argument\n",
3552 file, linenum, args[0]);
3553 err_code |= ERR_ALERT | ERR_FATAL;
3554 goto out;
3555 }
3556 else if (!strcmp(args[1], "use-backend-name"))
3557 curproxy->server_state_file_name = strdup(curproxy->id);
3558 else
3559 curproxy->server_state_file_name = strdup(args[1]);
3560 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003561 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003562 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003563 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003564
Willy Tarreaubaaee002006-06-26 02:48:02 +02003565 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003566 if (curproxy == &defproxy) {
3567 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3568 err_code |= ERR_ALERT | ERR_FATAL;
3569 goto out;
3570 }
3571
William Lallemand1a748ae2015-05-19 16:37:23 +02003572 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3573 goto out;
3574
Willy Tarreaubaaee002006-06-26 02:48:02 +02003575 if (*(args[4]) == 0) {
3576 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3577 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003578 err_code |= ERR_ALERT | ERR_FATAL;
3579 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003580 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003581 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003582 curproxy->capture_name = strdup(args[2]);
3583 curproxy->capture_namelen = strlen(curproxy->capture_name);
3584 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003585 curproxy->to_log |= LW_COOKIE;
3586 }
3587 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3588 struct cap_hdr *hdr;
3589
3590 if (curproxy == &defproxy) {
3591 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 +02003592 err_code |= ERR_ALERT | ERR_FATAL;
3593 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003594 }
3595
William Lallemand1a748ae2015-05-19 16:37:23 +02003596 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3597 goto out;
3598
Willy Tarreaubaaee002006-06-26 02:48:02 +02003599 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3600 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3601 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003602 err_code |= ERR_ALERT | ERR_FATAL;
3603 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003604 }
3605
3606 hdr = calloc(sizeof(struct cap_hdr), 1);
3607 hdr->next = curproxy->req_cap;
3608 hdr->name = strdup(args[3]);
3609 hdr->namelen = strlen(args[3]);
3610 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003611 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003612 hdr->index = curproxy->nb_req_cap++;
3613 curproxy->req_cap = hdr;
3614 curproxy->to_log |= LW_REQHDR;
3615 }
3616 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3617 struct cap_hdr *hdr;
3618
3619 if (curproxy == &defproxy) {
3620 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 +02003621 err_code |= ERR_ALERT | ERR_FATAL;
3622 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003623 }
3624
William Lallemand1a748ae2015-05-19 16:37:23 +02003625 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3626 goto out;
3627
Willy Tarreaubaaee002006-06-26 02:48:02 +02003628 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3629 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3630 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003631 err_code |= ERR_ALERT | ERR_FATAL;
3632 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003633 }
3634 hdr = calloc(sizeof(struct cap_hdr), 1);
3635 hdr->next = curproxy->rsp_cap;
3636 hdr->name = strdup(args[3]);
3637 hdr->namelen = strlen(args[3]);
3638 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003639 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003640 hdr->index = curproxy->nb_rsp_cap++;
3641 curproxy->rsp_cap = hdr;
3642 curproxy->to_log |= LW_RSPHDR;
3643 }
3644 else {
3645 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3646 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003647 err_code |= ERR_ALERT | ERR_FATAL;
3648 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003649 }
3650 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003651 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003652 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003653 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003654
William Lallemanddf1425a2015-04-28 20:17:49 +02003655 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3656 goto out;
3657
Willy Tarreaubaaee002006-06-26 02:48:02 +02003658 if (*(args[1]) == 0) {
3659 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3660 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003661 err_code |= ERR_ALERT | ERR_FATAL;
3662 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003663 }
3664 curproxy->conn_retries = atol(args[1]);
3665 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003666 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003667 struct act_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003668
3669 if (curproxy == &defproxy) {
3670 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3671 err_code |= ERR_ALERT | ERR_FATAL;
3672 goto out;
3673 }
3674
Willy Tarreau20b0de52012-12-24 15:45:22 +01003675 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003676 !LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003677 (LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3678 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_DENY ||
3679 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REDIR ||
3680 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REQ_AUTH)) {
Willy Tarreau20b0de52012-12-24 15:45:22 +01003681 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 +01003682 file, linenum, args[0]);
3683 err_code |= ERR_WARN;
3684 }
3685
Willy Tarreauff011f22011-01-06 17:51:27 +01003686 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003687
Willy Tarreauff011f22011-01-06 17:51:27 +01003688 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003689 err_code |= ERR_ALERT | ERR_ABORT;
3690 goto out;
3691 }
3692
Willy Tarreau5002f572014-04-23 01:32:02 +02003693 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003694 err_code |= warnif_cond_conflicts(rule->cond,
3695 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3696 file, linenum);
3697
Willy Tarreauff011f22011-01-06 17:51:27 +01003698 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003699 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003700 else if (!strcmp(args[0], "http-response")) { /* response access control */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003701 struct act_rule *rule;
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003702
3703 if (curproxy == &defproxy) {
3704 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3705 err_code |= ERR_ALERT | ERR_FATAL;
3706 goto out;
3707 }
3708
3709 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003710 !LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003711 (LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3712 LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_DENY)) {
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003713 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3714 file, linenum, args[0]);
3715 err_code |= ERR_WARN;
3716 }
3717
3718 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3719
3720 if (!rule) {
3721 err_code |= ERR_ALERT | ERR_ABORT;
3722 goto out;
3723 }
3724
3725 err_code |= warnif_cond_conflicts(rule->cond,
3726 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3727 file, linenum);
3728
3729 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3730 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003731 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3732 /* set the header name and length into the proxy structure */
3733 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3734 err_code |= ERR_WARN;
3735
3736 if (!*args[1]) {
3737 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3738 file, linenum, args[0]);
3739 err_code |= ERR_ALERT | ERR_FATAL;
3740 goto out;
3741 }
3742
3743 /* set the desired header name */
3744 free(curproxy->server_id_hdr_name);
3745 curproxy->server_id_hdr_name = strdup(args[1]);
3746 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3747 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003748 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003749 struct act_rule *rule;
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003750
Willy Tarreaub099aca2008-10-12 17:26:37 +02003751 if (curproxy == &defproxy) {
3752 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003753 err_code |= ERR_ALERT | ERR_FATAL;
3754 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003755 }
3756
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003757 /* emulate "block" using "http-request block". Since these rules are supposed to
3758 * be processed before all http-request rules, we put them into their own list
3759 * and will insert them at the end.
3760 */
3761 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3762 if (!rule) {
3763 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003764 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003765 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003766 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3767 err_code |= warnif_cond_conflicts(rule->cond,
3768 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3769 file, linenum);
3770 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003771
3772 if (!already_warned(WARN_BLOCK_DEPRECATED))
3773 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]);
3774
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003775 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003776 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003777 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003778
Cyril Bonté99ed3272010-01-24 23:29:44 +01003779 if (curproxy == &defproxy) {
3780 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3781 err_code |= ERR_ALERT | ERR_FATAL;
3782 goto out;
3783 }
3784
Willy Tarreaube4653b2015-05-28 15:26:58 +02003785 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003786 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3787 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003788 err_code |= ERR_ALERT | ERR_FATAL;
3789 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003790 }
3791
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003792 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003793 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003794 err_code |= warnif_cond_conflicts(rule->cond,
3795 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3796 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003797 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003798 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003799 struct switching_rule *rule;
3800
Willy Tarreaub099aca2008-10-12 17:26:37 +02003801 if (curproxy == &defproxy) {
3802 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003803 err_code |= ERR_ALERT | ERR_FATAL;
3804 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003805 }
3806
Willy Tarreau55ea7572007-06-17 19:56:27 +02003807 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003808 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003809
3810 if (*(args[1]) == 0) {
3811 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003812 err_code |= ERR_ALERT | ERR_FATAL;
3813 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003814 }
3815
Willy Tarreauf51658d2014-04-23 01:21:56 +02003816 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3817 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3818 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3819 file, linenum, errmsg);
3820 err_code |= ERR_ALERT | ERR_FATAL;
3821 goto out;
3822 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003823
Willy Tarreauf51658d2014-04-23 01:21:56 +02003824 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003825 }
3826
3827 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
3828 rule->cond = cond;
3829 rule->be.name = strdup(args[1]);
3830 LIST_INIT(&rule->list);
3831 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3832 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003833 else if (strcmp(args[0], "use-server") == 0) {
3834 struct server_rule *rule;
3835
3836 if (curproxy == &defproxy) {
3837 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3838 err_code |= ERR_ALERT | ERR_FATAL;
3839 goto out;
3840 }
3841
3842 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3843 err_code |= ERR_WARN;
3844
3845 if (*(args[1]) == 0) {
3846 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3847 err_code |= ERR_ALERT | ERR_FATAL;
3848 goto out;
3849 }
3850
3851 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3852 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3853 file, linenum, args[0]);
3854 err_code |= ERR_ALERT | ERR_FATAL;
3855 goto out;
3856 }
3857
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003858 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3859 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3860 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003861 err_code |= ERR_ALERT | ERR_FATAL;
3862 goto out;
3863 }
3864
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003865 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003866
3867 rule = (struct server_rule *)calloc(1, sizeof(*rule));
3868 rule->cond = cond;
3869 rule->srv.name = strdup(args[1]);
3870 LIST_INIT(&rule->list);
3871 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3872 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3873 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003874 else if ((!strcmp(args[0], "force-persist")) ||
3875 (!strcmp(args[0], "ignore-persist"))) {
3876 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003877
3878 if (curproxy == &defproxy) {
3879 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3880 err_code |= ERR_ALERT | ERR_FATAL;
3881 goto out;
3882 }
3883
3884 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3885 err_code |= ERR_WARN;
3886
Willy Tarreauef6494c2010-01-28 17:12:36 +01003887 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003888 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3889 file, linenum, args[0]);
3890 err_code |= ERR_ALERT | ERR_FATAL;
3891 goto out;
3892 }
3893
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003894 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3895 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3896 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003897 err_code |= ERR_ALERT | ERR_FATAL;
3898 goto out;
3899 }
3900
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003901 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3902 * where force-persist is applied.
3903 */
3904 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003905
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003906 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003907 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003908 if (!strcmp(args[0], "force-persist")) {
3909 rule->type = PERSIST_TYPE_FORCE;
3910 } else {
3911 rule->type = PERSIST_TYPE_IGNORE;
3912 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003913 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003914 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003915 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003916 else if (!strcmp(args[0], "stick-table")) {
3917 int myidx = 1;
Willy Tarreaue45288c2015-05-26 10:49:46 +02003918 struct proxy *other;
3919
Willy Tarreaue2dc1fa2015-05-26 12:08:07 +02003920 other = proxy_tbl_by_name(curproxy->id);
Willy Tarreaue45288c2015-05-26 10:49:46 +02003921 if (other) {
3922 Alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
3923 file, linenum, curproxy->id, proxy_type_str(other), other->id, other->conf.file, other->conf.line);
3924 err_code |= ERR_ALERT | ERR_FATAL;
3925 goto out;
3926 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003927
Emeric Brun32da3c42010-09-23 18:39:19 +02003928 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003929 curproxy->table.type = (unsigned int)-1;
3930 while (*args[myidx]) {
3931 const char *err;
3932
3933 if (strcmp(args[myidx], "size") == 0) {
3934 myidx++;
3935 if (!*(args[myidx])) {
3936 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3937 file, linenum, args[myidx-1]);
3938 err_code |= ERR_ALERT | ERR_FATAL;
3939 goto out;
3940 }
3941 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3942 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3943 file, linenum, *err, args[myidx-1]);
3944 err_code |= ERR_ALERT | ERR_FATAL;
3945 goto out;
3946 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003947 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003948 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003949 else if (strcmp(args[myidx], "peers") == 0) {
3950 myidx++;
Godbach50523162013-12-11 19:48:57 +08003951 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003952 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3953 file, linenum, args[myidx-1]);
3954 err_code |= ERR_ALERT | ERR_FATAL;
3955 goto out;
Godbach50523162013-12-11 19:48:57 +08003956 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003957 curproxy->table.peers.name = strdup(args[myidx++]);
3958 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003959 else if (strcmp(args[myidx], "expire") == 0) {
3960 myidx++;
3961 if (!*(args[myidx])) {
3962 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3963 file, linenum, args[myidx-1]);
3964 err_code |= ERR_ALERT | ERR_FATAL;
3965 goto out;
3966 }
3967 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3968 if (err) {
3969 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3970 file, linenum, *err, args[myidx-1]);
3971 err_code |= ERR_ALERT | ERR_FATAL;
3972 goto out;
3973 }
Ben Cabot3b90f0a2016-01-20 09:44:39 +00003974 if (val > INT_MAX) {
3975 Alert("parsing [%s:%d] : Expire value [%u]ms exceeds maxmimum value of 24.85 days.\n",
3976 file, linenum, val);
3977 err_code |= ERR_ALERT | ERR_FATAL;
3978 goto out;
3979 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003980 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003981 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003982 }
3983 else if (strcmp(args[myidx], "nopurge") == 0) {
3984 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003985 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003986 }
3987 else if (strcmp(args[myidx], "type") == 0) {
3988 myidx++;
3989 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3990 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3991 file, linenum, args[myidx]);
3992 err_code |= ERR_ALERT | ERR_FATAL;
3993 goto out;
3994 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003995 /* myidx already points to next arg */
3996 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003997 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003998 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003999 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02004000
4001 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004002 nw = args[myidx];
4003 while (*nw) {
4004 /* the "store" keyword supports a comma-separated list */
4005 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02004006 sa = NULL; /* store arg */
4007 while (*nw && *nw != ',') {
4008 if (*nw == '(') {
4009 *nw = 0;
4010 sa = ++nw;
4011 while (*nw != ')') {
4012 if (!*nw) {
4013 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
4014 file, linenum, args[0], cw);
4015 err_code |= ERR_ALERT | ERR_FATAL;
4016 goto out;
4017 }
4018 nw++;
4019 }
4020 *nw = '\0';
4021 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004022 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02004023 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004024 if (*nw)
4025 *nw++ = '\0';
4026 type = stktable_get_data_type(cw);
4027 if (type < 0) {
4028 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
4029 file, linenum, args[0], cw);
4030 err_code |= ERR_ALERT | ERR_FATAL;
4031 goto out;
4032 }
Willy Tarreauac782882010-06-20 10:41:54 +02004033
4034 err = stktable_alloc_data_type(&curproxy->table, type, sa);
4035 switch (err) {
4036 case PE_NONE: break;
4037 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004038 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
4039 file, linenum, args[0], cw);
4040 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02004041 break;
4042
4043 case PE_ARG_MISSING:
4044 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
4045 file, linenum, args[0], cw);
4046 err_code |= ERR_ALERT | ERR_FATAL;
4047 goto out;
4048
4049 case PE_ARG_NOT_USED:
4050 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
4051 file, linenum, args[0], cw);
4052 err_code |= ERR_ALERT | ERR_FATAL;
4053 goto out;
4054
4055 default:
4056 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
4057 file, linenum, args[0], cw);
4058 err_code |= ERR_ALERT | ERR_FATAL;
4059 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004060 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004061 }
4062 myidx++;
4063 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004064 else {
4065 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
4066 file, linenum, args[myidx]);
4067 err_code |= ERR_ALERT | ERR_FATAL;
4068 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004069 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004070 }
4071
4072 if (!curproxy->table.size) {
4073 Alert("parsing [%s:%d] : stick-table: missing size.\n",
4074 file, linenum);
4075 err_code |= ERR_ALERT | ERR_FATAL;
4076 goto out;
4077 }
4078
4079 if (curproxy->table.type == (unsigned int)-1) {
4080 Alert("parsing [%s:%d] : stick-table: missing type.\n",
4081 file, linenum);
4082 err_code |= ERR_ALERT | ERR_FATAL;
4083 goto out;
4084 }
4085 }
4086 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004087 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02004088 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004089 int myidx = 0;
4090 const char *name = NULL;
4091 int flags;
4092
4093 if (curproxy == &defproxy) {
4094 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4095 err_code |= ERR_ALERT | ERR_FATAL;
4096 goto out;
4097 }
4098
4099 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
4100 err_code |= ERR_WARN;
4101 goto out;
4102 }
4103
4104 myidx++;
4105 if ((strcmp(args[myidx], "store") == 0) ||
4106 (strcmp(args[myidx], "store-request") == 0)) {
4107 myidx++;
4108 flags = STK_IS_STORE;
4109 }
4110 else if (strcmp(args[myidx], "store-response") == 0) {
4111 myidx++;
4112 flags = STK_IS_STORE | STK_ON_RSP;
4113 }
4114 else if (strcmp(args[myidx], "match") == 0) {
4115 myidx++;
4116 flags = STK_IS_MATCH;
4117 }
4118 else if (strcmp(args[myidx], "on") == 0) {
4119 myidx++;
4120 flags = STK_IS_MATCH | STK_IS_STORE;
4121 }
4122 else {
4123 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
4124 err_code |= ERR_ALERT | ERR_FATAL;
4125 goto out;
4126 }
4127
4128 if (*(args[myidx]) == 0) {
4129 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
4130 err_code |= ERR_ALERT | ERR_FATAL;
4131 goto out;
4132 }
4133
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004134 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01004135 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004136 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01004137 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004138 err_code |= ERR_ALERT | ERR_FATAL;
4139 goto out;
4140 }
4141
4142 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01004143 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
4144 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
4145 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004146 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004147 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004148 goto out;
4149 }
4150 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01004151 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
4152 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
4153 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004154 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004155 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004156 goto out;
4157 }
4158 }
4159
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004160 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01004161 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004162
Emeric Brunb982a3d2010-01-04 15:45:53 +01004163 if (strcmp(args[myidx], "table") == 0) {
4164 myidx++;
4165 name = args[myidx++];
4166 }
4167
Willy Tarreauef6494c2010-01-28 17:12:36 +01004168 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004169 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
4170 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
4171 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004172 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004173 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004174 goto out;
4175 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004176 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01004177 else if (*(args[myidx])) {
4178 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
4179 file, linenum, args[0], args[myidx]);
4180 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004181 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01004182 goto out;
4183 }
Emeric Brun97679e72010-09-23 17:56:44 +02004184 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004185 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02004186 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004187 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01004188
Emeric Brunb982a3d2010-01-04 15:45:53 +01004189 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
4190 rule->cond = cond;
4191 rule->expr = expr;
4192 rule->flags = flags;
4193 rule->table.name = name ? strdup(name) : NULL;
4194 LIST_INIT(&rule->list);
4195 if (flags & STK_ON_RSP)
4196 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
4197 else
4198 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
4199 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004200 else if (!strcmp(args[0], "stats")) {
4201 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
4202 curproxy->uri_auth = NULL; /* we must detach from the default config */
4203
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004204 if (!*args[1]) {
4205 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02004206 } else if (!strcmp(args[1], "admin")) {
4207 struct stats_admin_rule *rule;
4208
4209 if (curproxy == &defproxy) {
4210 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
4211 err_code |= ERR_ALERT | ERR_FATAL;
4212 goto out;
4213 }
4214
4215 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4216 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4217 err_code |= ERR_ALERT | ERR_ABORT;
4218 goto out;
4219 }
4220
4221 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4222 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4223 file, linenum, args[0], args[1]);
4224 err_code |= ERR_ALERT | ERR_FATAL;
4225 goto out;
4226 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004227 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4228 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
4229 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02004230 err_code |= ERR_ALERT | ERR_FATAL;
4231 goto out;
4232 }
4233
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004234 err_code |= warnif_cond_conflicts(cond,
4235 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4236 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02004237
4238 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
4239 rule->cond = cond;
4240 LIST_INIT(&rule->list);
4241 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004242 } else if (!strcmp(args[1], "uri")) {
4243 if (*(args[2]) == 0) {
4244 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004245 err_code |= ERR_ALERT | ERR_FATAL;
4246 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004247 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
4248 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004249 err_code |= ERR_ALERT | ERR_ABORT;
4250 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004251 }
4252 } else if (!strcmp(args[1], "realm")) {
4253 if (*(args[2]) == 0) {
4254 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004255 err_code |= ERR_ALERT | ERR_FATAL;
4256 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004257 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
4258 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004259 err_code |= ERR_ALERT | ERR_ABORT;
4260 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004261 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02004262 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004263 unsigned interval;
4264
4265 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
4266 if (err) {
4267 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
4268 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004269 err_code |= ERR_ALERT | ERR_FATAL;
4270 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004271 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
4272 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004273 err_code |= ERR_ALERT | ERR_ABORT;
4274 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004275 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004276 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004277 struct act_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004278
4279 if (curproxy == &defproxy) {
4280 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4281 err_code |= ERR_ALERT | ERR_FATAL;
4282 goto out;
4283 }
4284
4285 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4286 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4287 err_code |= ERR_ALERT | ERR_ABORT;
4288 goto out;
4289 }
4290
Willy Tarreauff011f22011-01-06 17:51:27 +01004291 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004292 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct act_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004293 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
4294 file, linenum, args[0]);
4295 err_code |= ERR_WARN;
4296 }
4297
Willy Tarreauff011f22011-01-06 17:51:27 +01004298 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004299
Willy Tarreauff011f22011-01-06 17:51:27 +01004300 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004301 err_code |= ERR_ALERT | ERR_ABORT;
4302 goto out;
4303 }
4304
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004305 err_code |= warnif_cond_conflicts(rule->cond,
4306 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4307 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01004308 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004309
Willy Tarreaubaaee002006-06-26 02:48:02 +02004310 } else if (!strcmp(args[1], "auth")) {
4311 if (*(args[2]) == 0) {
4312 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004313 err_code |= ERR_ALERT | ERR_FATAL;
4314 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004315 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
4316 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004317 err_code |= ERR_ALERT | ERR_ABORT;
4318 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004319 }
4320 } else if (!strcmp(args[1], "scope")) {
4321 if (*(args[2]) == 0) {
4322 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004323 err_code |= ERR_ALERT | ERR_FATAL;
4324 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004325 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
4326 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004327 err_code |= ERR_ALERT | ERR_ABORT;
4328 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004329 }
4330 } else if (!strcmp(args[1], "enable")) {
4331 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4332 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004333 err_code |= ERR_ALERT | ERR_ABORT;
4334 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004335 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004336 } else if (!strcmp(args[1], "hide-version")) {
4337 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
4338 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004339 err_code |= ERR_ALERT | ERR_ABORT;
4340 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004341 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01004342 } else if (!strcmp(args[1], "show-legends")) {
4343 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
4344 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4345 err_code |= ERR_ALERT | ERR_ABORT;
4346 goto out;
4347 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004348 } else if (!strcmp(args[1], "show-node")) {
4349
4350 if (*args[2]) {
4351 int i;
4352 char c;
4353
4354 for (i=0; args[2][i]; i++) {
4355 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01004356 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
4357 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004358 break;
4359 }
4360
4361 if (!i || args[2][i]) {
4362 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
4363 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
4364 file, linenum, args[0], args[1]);
4365 err_code |= ERR_ALERT | ERR_FATAL;
4366 goto out;
4367 }
4368 }
4369
4370 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
4371 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4372 err_code |= ERR_ALERT | ERR_ABORT;
4373 goto out;
4374 }
4375 } else if (!strcmp(args[1], "show-desc")) {
4376 char *desc = NULL;
4377
4378 if (*args[2]) {
4379 int i, len=0;
4380 char *d;
4381
Willy Tarreau348acfe2014-04-14 15:00:39 +02004382 for (i = 2; *args[i]; i++)
4383 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004384
4385 desc = d = (char *)calloc(1, len);
4386
Willy Tarreau348acfe2014-04-14 15:00:39 +02004387 d += snprintf(d, desc + len - d, "%s", args[2]);
4388 for (i = 3; *args[i]; i++)
4389 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004390 }
4391
4392 if (!*args[2] && !global.desc)
4393 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
4394 file, linenum, args[1]);
4395 else {
4396 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
4397 free(desc);
4398 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4399 err_code |= ERR_ALERT | ERR_ABORT;
4400 goto out;
4401 }
4402 free(desc);
4403 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004404 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004405stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02004406 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 +01004407 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004408 err_code |= ERR_ALERT | ERR_FATAL;
4409 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004410 }
4411 }
4412 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004413 int optnum;
4414
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004415 if (*(args[1]) == '\0') {
4416 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
4417 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004418 err_code |= ERR_ALERT | ERR_FATAL;
4419 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004420 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01004421
4422 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
4423 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004424 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
4425 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4426 file, linenum, cfg_opts[optnum].name);
4427 err_code |= ERR_ALERT | ERR_FATAL;
4428 goto out;
4429 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004430 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4431 goto out;
4432
Willy Tarreau93893792009-07-23 13:19:11 +02004433 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
4434 err_code |= ERR_WARN;
4435 goto out;
4436 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004437
Willy Tarreau3842f002009-06-14 11:39:52 +02004438 curproxy->no_options &= ~cfg_opts[optnum].val;
4439 curproxy->options &= ~cfg_opts[optnum].val;
4440
4441 switch (kwm) {
4442 case KWM_STD:
4443 curproxy->options |= cfg_opts[optnum].val;
4444 break;
4445 case KWM_NO:
4446 curproxy->no_options |= cfg_opts[optnum].val;
4447 break;
4448 case KWM_DEF: /* already cleared */
4449 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004450 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004451
Willy Tarreau93893792009-07-23 13:19:11 +02004452 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004453 }
4454 }
4455
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004456 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
4457 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004458 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
4459 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4460 file, linenum, cfg_opts2[optnum].name);
4461 err_code |= ERR_ALERT | ERR_FATAL;
4462 goto out;
4463 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004464 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4465 goto out;
Willy Tarreau93893792009-07-23 13:19:11 +02004466 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4467 err_code |= ERR_WARN;
4468 goto out;
4469 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004470
Willy Tarreau3842f002009-06-14 11:39:52 +02004471 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4472 curproxy->options2 &= ~cfg_opts2[optnum].val;
4473
4474 switch (kwm) {
4475 case KWM_STD:
4476 curproxy->options2 |= cfg_opts2[optnum].val;
4477 break;
4478 case KWM_NO:
4479 curproxy->no_options2 |= cfg_opts2[optnum].val;
4480 break;
4481 case KWM_DEF: /* already cleared */
4482 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004483 }
Willy Tarreau93893792009-07-23 13:19:11 +02004484 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004485 }
4486 }
4487
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004488 /* HTTP options override each other. They can be cancelled using
4489 * "no option xxx" which only switches to default mode if the mode
4490 * was this one (useful for cancelling options set in defaults
4491 * sections).
4492 */
4493 if (strcmp(args[1], "httpclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004494 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4495 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004496 if (kwm == KWM_STD) {
4497 curproxy->options &= ~PR_O_HTTP_MODE;
4498 curproxy->options |= PR_O_HTTP_PCL;
4499 goto out;
4500 }
4501 else if (kwm == KWM_NO) {
4502 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4503 curproxy->options &= ~PR_O_HTTP_MODE;
4504 goto out;
4505 }
4506 }
4507 else if (strcmp(args[1], "forceclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004508 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4509 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004510 if (kwm == KWM_STD) {
4511 curproxy->options &= ~PR_O_HTTP_MODE;
4512 curproxy->options |= PR_O_HTTP_FCL;
4513 goto out;
4514 }
4515 else if (kwm == KWM_NO) {
4516 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4517 curproxy->options &= ~PR_O_HTTP_MODE;
4518 goto out;
4519 }
4520 }
4521 else if (strcmp(args[1], "http-server-close") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004522 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4523 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004524 if (kwm == KWM_STD) {
4525 curproxy->options &= ~PR_O_HTTP_MODE;
4526 curproxy->options |= PR_O_HTTP_SCL;
4527 goto out;
4528 }
4529 else if (kwm == KWM_NO) {
4530 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4531 curproxy->options &= ~PR_O_HTTP_MODE;
4532 goto out;
4533 }
4534 }
4535 else if (strcmp(args[1], "http-keep-alive") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004536 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4537 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004538 if (kwm == KWM_STD) {
4539 curproxy->options &= ~PR_O_HTTP_MODE;
4540 curproxy->options |= PR_O_HTTP_KAL;
4541 goto out;
4542 }
4543 else if (kwm == KWM_NO) {
4544 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4545 curproxy->options &= ~PR_O_HTTP_MODE;
4546 goto out;
4547 }
4548 }
4549 else if (strcmp(args[1], "http-tunnel") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004550 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4551 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004552 if (kwm == KWM_STD) {
4553 curproxy->options &= ~PR_O_HTTP_MODE;
4554 curproxy->options |= PR_O_HTTP_TUN;
4555 goto out;
4556 }
4557 else if (kwm == KWM_NO) {
4558 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4559 curproxy->options &= ~PR_O_HTTP_MODE;
4560 goto out;
4561 }
4562 }
4563
Joseph Lynch726ab712015-05-11 23:25:34 -07004564 /* Redispatch can take an integer argument that control when the
4565 * resispatch occurs. All values are relative to the retries option.
4566 * This can be cancelled using "no option xxx".
4567 */
4568 if (strcmp(args[1], "redispatch") == 0) {
4569 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
4570 err_code |= ERR_WARN;
4571 goto out;
4572 }
4573
4574 curproxy->no_options &= ~PR_O_REDISP;
4575 curproxy->options &= ~PR_O_REDISP;
4576
4577 switch (kwm) {
4578 case KWM_STD:
4579 curproxy->options |= PR_O_REDISP;
4580 curproxy->redispatch_after = -1;
4581 if(*args[2]) {
4582 curproxy->redispatch_after = atol(args[2]);
4583 }
4584 break;
4585 case KWM_NO:
4586 curproxy->no_options |= PR_O_REDISP;
4587 curproxy->redispatch_after = 0;
4588 break;
4589 case KWM_DEF: /* already cleared */
4590 break;
4591 }
4592 goto out;
4593 }
4594
Willy Tarreau3842f002009-06-14 11:39:52 +02004595 if (kwm != KWM_STD) {
4596 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004597 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004598 err_code |= ERR_ALERT | ERR_FATAL;
4599 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004600 }
4601
Emeric Brun3a058f32009-06-30 18:26:00 +02004602 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004603 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004604 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004605 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004606 if (*(args[2]) != '\0') {
4607 if (!strcmp(args[2], "clf")) {
4608 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004609 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004610 } else {
William Lallemand77063bc2015-05-28 18:02:48 +02004611 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004612 err_code |= ERR_ALERT | ERR_FATAL;
4613 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004614 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004615 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
4616 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004617 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004618 if (curproxy->conf.logformat_string != default_http_log_format &&
4619 curproxy->conf.logformat_string != default_tcp_log_format &&
4620 curproxy->conf.logformat_string != clf_http_log_format)
4621 free(curproxy->conf.logformat_string);
4622 curproxy->conf.logformat_string = logformat;
4623
4624 free(curproxy->conf.lfs_file);
4625 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4626 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004627 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004628 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004629 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004630 if (curproxy->conf.logformat_string != default_http_log_format &&
4631 curproxy->conf.logformat_string != default_tcp_log_format &&
4632 curproxy->conf.logformat_string != clf_http_log_format)
4633 free(curproxy->conf.logformat_string);
4634 curproxy->conf.logformat_string = default_tcp_log_format;
4635
4636 free(curproxy->conf.lfs_file);
4637 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4638 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemanddf1425a2015-04-28 20:17:49 +02004639
4640 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4641 goto out;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004642 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004643 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004644 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004645 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004646 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004647
William Lallemanddf1425a2015-04-28 20:17:49 +02004648 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4649 goto out;
4650
Willy Tarreau13943ab2006-12-31 00:24:10 +01004651 if (curproxy->cap & PR_CAP_FE)
4652 curproxy->options |= PR_O_TCP_CLI_KA;
4653 if (curproxy->cap & PR_CAP_BE)
4654 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004655 }
4656 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004657 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004658 err_code |= ERR_WARN;
4659
Willy Tarreaubaaee002006-06-26 02:48:02 +02004660 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004661 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004662 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004663 curproxy->options2 &= ~PR_O2_CHK_ANY;
4664 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004665 if (!*args[2]) { /* no argument */
4666 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4667 curproxy->check_len = strlen(DEF_CHECK_REQ);
4668 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004669 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004670 curproxy->check_req = (char *)malloc(reqlen);
4671 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004672 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004673 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004674 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004675 if (*args[4])
4676 reqlen += strlen(args[4]);
4677 else
4678 reqlen += strlen("HTTP/1.0");
4679
4680 curproxy->check_req = (char *)malloc(reqlen);
4681 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004682 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004683 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004684 if (alertif_too_many_args_idx(3, 1, file, linenum, args, &err_code))
4685 goto out;
Willy Tarreauf3c69202006-07-09 16:42:34 +02004686 }
4687 else if (!strcmp(args[1], "ssl-hello-chk")) {
4688 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004689 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004690 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004691
Willy Tarreaua534fea2008-08-03 12:19:50 +02004692 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004693 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004694 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004695 curproxy->options2 |= PR_O2_SSL3_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004696
4697 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4698 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004699 }
Willy Tarreau23677902007-05-08 23:50:35 +02004700 else if (!strcmp(args[1], "smtpchk")) {
4701 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004702 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004703 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004704 curproxy->options2 &= ~PR_O2_CHK_ANY;
4705 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004706
4707 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4708 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4709 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4710 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4711 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4712 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
4713 curproxy->check_req = (char *)malloc(reqlen);
4714 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4715 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4716 } else {
4717 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4718 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4719 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4720 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4721 }
4722 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004723 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4724 goto out;
Willy Tarreau23677902007-05-08 23:50:35 +02004725 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004726 else if (!strcmp(args[1], "pgsql-check")) {
4727 /* use PostgreSQL request to check servers' health */
4728 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4729 err_code |= ERR_WARN;
4730
4731 free(curproxy->check_req);
4732 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004733 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004734 curproxy->options2 |= PR_O2_PGSQL_CHK;
4735
4736 if (*(args[2])) {
4737 int cur_arg = 2;
4738
4739 while (*(args[cur_arg])) {
4740 if (strcmp(args[cur_arg], "user") == 0) {
4741 char * packet;
4742 uint32_t packet_len;
4743 uint32_t pv;
4744
4745 /* suboption header - needs additional argument for it */
4746 if (*(args[cur_arg+1]) == 0) {
4747 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4748 file, linenum, args[0], args[1], args[cur_arg]);
4749 err_code |= ERR_ALERT | ERR_FATAL;
4750 goto out;
4751 }
4752
4753 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4754 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4755 pv = htonl(0x30000); /* protocol version 3.0 */
4756
4757 packet = (char*) calloc(1, packet_len);
4758
4759 memcpy(packet + 4, &pv, 4);
4760
4761 /* copy "user" */
4762 memcpy(packet + 8, "user", 4);
4763
4764 /* copy username */
4765 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4766
4767 free(curproxy->check_req);
4768 curproxy->check_req = packet;
4769 curproxy->check_len = packet_len;
4770
4771 packet_len = htonl(packet_len);
4772 memcpy(packet, &packet_len, 4);
4773 cur_arg += 2;
4774 } else {
4775 /* unknown suboption - catchall */
4776 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4777 file, linenum, args[0], args[1]);
4778 err_code |= ERR_ALERT | ERR_FATAL;
4779 goto out;
4780 }
4781 } /* end while loop */
4782 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004783 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4784 goto out;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004785 }
4786
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004787 else if (!strcmp(args[1], "redis-check")) {
4788 /* use REDIS PING request to check servers' health */
4789 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4790 err_code |= ERR_WARN;
4791
4792 free(curproxy->check_req);
4793 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004794 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004795 curproxy->options2 |= PR_O2_REDIS_CHK;
4796
4797 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
4798 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4799 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004800
4801 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4802 goto out;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004803 }
4804
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004805 else if (!strcmp(args[1], "mysql-check")) {
4806 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004807 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4808 err_code |= ERR_WARN;
4809
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004810 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004811 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004812 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004813 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004814
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004815 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004816 * const char mysql40_client_auth_pkt[] = {
4817 * "\x0e\x00\x00" // packet length
4818 * "\x01" // packet number
4819 * "\x00\x00" // client capabilities
4820 * "\x00\x00\x01" // max packet
4821 * "haproxy\x00" // username (null terminated string)
4822 * "\x00" // filler (always 0x00)
4823 * "\x01\x00\x00" // packet length
4824 * "\x00" // packet number
4825 * "\x01" // COM_QUIT command
4826 * };
4827 */
4828
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004829 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4830 * const char mysql41_client_auth_pkt[] = {
4831 * "\x0e\x00\x00\" // packet length
4832 * "\x01" // packet number
4833 * "\x00\x00\x00\x00" // client capabilities
4834 * "\x00\x00\x00\x01" // max packet
4835 * "\x21" // character set (UTF-8)
4836 * char[23] // All zeroes
4837 * "haproxy\x00" // username (null terminated string)
4838 * "\x00" // filler (always 0x00)
4839 * "\x01\x00\x00" // packet length
4840 * "\x00" // packet number
4841 * "\x01" // COM_QUIT command
4842 * };
4843 */
4844
4845
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004846 if (*(args[2])) {
4847 int cur_arg = 2;
4848
4849 while (*(args[cur_arg])) {
4850 if (strcmp(args[cur_arg], "user") == 0) {
4851 char *mysqluser;
4852 int packetlen, reqlen, userlen;
4853
4854 /* suboption header - needs additional argument for it */
4855 if (*(args[cur_arg+1]) == 0) {
4856 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4857 file, linenum, args[0], args[1], args[cur_arg]);
4858 err_code |= ERR_ALERT | ERR_FATAL;
4859 goto out;
4860 }
4861 mysqluser = args[cur_arg + 1];
4862 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004863
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004864 if (*(args[cur_arg+2])) {
4865 if (!strcmp(args[cur_arg+2], "post-41")) {
4866 packetlen = userlen + 7 + 27;
4867 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004868
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004869 free(curproxy->check_req);
4870 curproxy->check_req = (char *)calloc(1, reqlen);
4871 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004872
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004873 snprintf(curproxy->check_req, 4, "%c%c%c",
4874 ((unsigned char) packetlen & 0xff),
4875 ((unsigned char) (packetlen >> 8) & 0xff),
4876 ((unsigned char) (packetlen >> 16) & 0xff));
4877
4878 curproxy->check_req[3] = 1;
4879 curproxy->check_req[5] = 130;
4880 curproxy->check_req[11] = 1;
4881 curproxy->check_req[12] = 33;
4882 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4883 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4884 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4885 cur_arg += 3;
4886 } else {
4887 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4888 err_code |= ERR_ALERT | ERR_FATAL;
4889 goto out;
4890 }
4891 } else {
4892 packetlen = userlen + 7;
4893 reqlen = packetlen + 9;
4894
4895 free(curproxy->check_req);
4896 curproxy->check_req = (char *)calloc(1, reqlen);
4897 curproxy->check_len = reqlen;
4898
4899 snprintf(curproxy->check_req, 4, "%c%c%c",
4900 ((unsigned char) packetlen & 0xff),
4901 ((unsigned char) (packetlen >> 8) & 0xff),
4902 ((unsigned char) (packetlen >> 16) & 0xff));
4903
4904 curproxy->check_req[3] = 1;
4905 curproxy->check_req[5] = 128;
4906 curproxy->check_req[8] = 1;
4907 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4908 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4909 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4910 cur_arg += 2;
4911 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004912 } else {
4913 /* unknown suboption - catchall */
4914 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4915 file, linenum, args[0], args[1]);
4916 err_code |= ERR_ALERT | ERR_FATAL;
4917 goto out;
4918 }
4919 } /* end while loop */
4920 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004921 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004922 else if (!strcmp(args[1], "ldap-check")) {
4923 /* use LDAP request to check servers' health */
4924 free(curproxy->check_req);
4925 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004926 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004927 curproxy->options2 |= PR_O2_LDAP_CHK;
4928
4929 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
4930 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
4931 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004932 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4933 goto out;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004934 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004935 else if (!strcmp(args[1], "tcp-check")) {
4936 /* use raw TCPCHK send/expect to check servers' health */
4937 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4938 err_code |= ERR_WARN;
4939
4940 free(curproxy->check_req);
4941 curproxy->check_req = NULL;
4942 curproxy->options2 &= ~PR_O2_CHK_ANY;
4943 curproxy->options2 |= PR_O2_TCPCHK_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004944 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4945 goto out;
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004946 }
Simon Horman98637e52014-06-20 12:30:16 +09004947 else if (!strcmp(args[1], "external-check")) {
4948 /* excute an external command to check servers' health */
4949 free(curproxy->check_req);
4950 curproxy->check_req = NULL;
4951 curproxy->options2 &= ~PR_O2_CHK_ANY;
4952 curproxy->options2 |= PR_O2_EXT_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004953 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4954 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09004955 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004956 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004957 int cur_arg;
4958
4959 /* insert x-forwarded-for field, but not for the IP address listed as an except.
4960 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004961 */
Ross Westaf72a1d2008-08-03 10:51:45 +02004962
Willy Tarreau87cf5142011-08-19 22:57:24 +02004963 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02004964
4965 free(curproxy->fwdfor_hdr_name);
4966 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
4967 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
4968
4969 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
4970 cur_arg = 2;
4971 while (*(args[cur_arg])) {
4972 if (!strcmp(args[cur_arg], "except")) {
4973 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004974 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004975 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4976 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004977 err_code |= ERR_ALERT | ERR_FATAL;
4978 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004979 }
4980 /* flush useless bits */
4981 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02004982 cur_arg += 2;
4983 } else if (!strcmp(args[cur_arg], "header")) {
4984 /* suboption header - needs additional argument for it */
4985 if (*(args[cur_arg+1]) == 0) {
4986 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4987 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004988 err_code |= ERR_ALERT | ERR_FATAL;
4989 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02004990 }
4991 free(curproxy->fwdfor_hdr_name);
4992 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
4993 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
4994 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02004995 } else if (!strcmp(args[cur_arg], "if-none")) {
4996 curproxy->options &= ~PR_O_FF_ALWAYS;
4997 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004998 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02004999 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02005000 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02005001 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005002 err_code |= ERR_ALERT | ERR_FATAL;
5003 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005004 }
Ross Westaf72a1d2008-08-03 10:51:45 +02005005 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005006 }
Maik Broemme2850cb42009-04-17 18:53:21 +02005007 else if (!strcmp(args[1], "originalto")) {
5008 int cur_arg;
5009
5010 /* insert x-original-to field, but not for the IP address listed as an except.
5011 * set default options (ie: bitfield, header name, etc)
5012 */
5013
5014 curproxy->options |= PR_O_ORGTO;
5015
5016 free(curproxy->orgto_hdr_name);
5017 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
5018 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
5019
Willy Tarreau87cf5142011-08-19 22:57:24 +02005020 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02005021 cur_arg = 2;
5022 while (*(args[cur_arg])) {
5023 if (!strcmp(args[cur_arg], "except")) {
5024 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005025 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 +02005026 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5027 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005028 err_code |= ERR_ALERT | ERR_FATAL;
5029 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005030 }
5031 /* flush useless bits */
5032 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
5033 cur_arg += 2;
5034 } else if (!strcmp(args[cur_arg], "header")) {
5035 /* suboption header - needs additional argument for it */
5036 if (*(args[cur_arg+1]) == 0) {
5037 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5038 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005039 err_code |= ERR_ALERT | ERR_FATAL;
5040 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005041 }
5042 free(curproxy->orgto_hdr_name);
5043 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
5044 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
5045 cur_arg += 2;
5046 } else {
5047 /* unknown suboption - catchall */
5048 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
5049 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005050 err_code |= ERR_ALERT | ERR_FATAL;
5051 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005052 }
5053 } /* end while loop */
5054 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005055 else {
5056 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005057 err_code |= ERR_ALERT | ERR_FATAL;
5058 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005059 }
Willy Tarreau93893792009-07-23 13:19:11 +02005060 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005061 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005062 else if (!strcmp(args[0], "default_backend")) {
5063 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005064 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005065
5066 if (*(args[1]) == 0) {
5067 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005068 err_code |= ERR_ALERT | ERR_FATAL;
5069 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005070 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005071 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005072 curproxy->defbe.name = strdup(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005073
5074 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5075 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005076 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005077 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01005078 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005079 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005080
Willy Tarreaua3c504c2014-04-28 22:37:32 +02005081 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
5082 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 +01005083 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005084 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005085 /* enable reconnections to dispatch */
5086 curproxy->options |= PR_O_REDISP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005087
5088 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5089 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005090 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005091 else if (!strcmp(args[0], "http-reuse")) {
5092 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5093 err_code |= ERR_WARN;
5094
5095 if (strcmp(args[1], "never") == 0) {
5096 /* enable a graceful server shutdown on an HTTP 404 response */
5097 curproxy->options &= ~PR_O_REUSE_MASK;
5098 curproxy->options |= PR_O_REUSE_NEVR;
5099 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5100 goto out;
5101 }
Willy Tarreau161d45f2015-08-05 16:02:46 +02005102 else if (strcmp(args[1], "safe") == 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_SAFE;
5106 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5107 goto out;
5108 }
Willy Tarreau449d74a2015-08-05 17:16:33 +02005109 else if (strcmp(args[1], "aggressive") == 0) {
5110 curproxy->options &= ~PR_O_REUSE_MASK;
5111 curproxy->options |= PR_O_REUSE_AGGR;
5112 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5113 goto out;
5114 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005115 else if (strcmp(args[1], "always") == 0) {
5116 /* enable a graceful server shutdown on an HTTP 404 response */
5117 curproxy->options &= ~PR_O_REUSE_MASK;
5118 curproxy->options |= PR_O_REUSE_ALWS;
5119 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5120 goto out;
5121 }
5122 else {
Willy Tarreau449d74a2015-08-05 17:16:33 +02005123 Alert("parsing [%s:%d] : '%s' only supports 'never', 'safe', 'aggressive', 'always'.\n", file, linenum, args[0]);
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005124 err_code |= ERR_ALERT | ERR_FATAL;
5125 goto out;
5126 }
5127 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005128 else if (!strcmp(args[0], "http-check")) {
5129 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005130 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01005131
5132 if (strcmp(args[1], "disable-on-404") == 0) {
5133 /* enable a graceful server shutdown on an HTTP 404 response */
5134 curproxy->options |= PR_O_DISABLE404;
William Lallemanddf1425a2015-04-28 20:17:49 +02005135 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5136 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005137 }
Willy Tarreauef781042010-01-27 11:53:01 +01005138 else if (strcmp(args[1], "send-state") == 0) {
5139 /* enable emission of the apparent state of a server in HTTP checks */
5140 curproxy->options2 |= PR_O2_CHK_SNDST;
William Lallemanddf1425a2015-04-28 20:17:49 +02005141 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5142 goto out;
Willy Tarreauef781042010-01-27 11:53:01 +01005143 }
Willy Tarreaubd741542010-03-16 18:46:54 +01005144 else if (strcmp(args[1], "expect") == 0) {
5145 const char *ptr_arg;
5146 int cur_arg;
5147
5148 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5149 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5150 err_code |= ERR_ALERT | ERR_FATAL;
5151 goto out;
5152 }
5153
5154 cur_arg = 2;
5155 /* consider exclamation marks, sole or at the beginning of a word */
5156 while (*(ptr_arg = args[cur_arg])) {
5157 while (*ptr_arg == '!') {
5158 curproxy->options2 ^= PR_O2_EXP_INV;
5159 ptr_arg++;
5160 }
5161 if (*ptr_arg)
5162 break;
5163 cur_arg++;
5164 }
5165 /* now ptr_arg points to the beginning of a word past any possible
5166 * exclamation mark, and cur_arg is the argument which holds this word.
5167 */
5168 if (strcmp(ptr_arg, "status") == 0) {
5169 if (!*(args[cur_arg + 1])) {
5170 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5171 file, linenum, args[0], args[1], ptr_arg);
5172 err_code |= ERR_ALERT | ERR_FATAL;
5173 goto out;
5174 }
5175 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005176 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005177 curproxy->expect_str = strdup(args[cur_arg + 1]);
5178 }
5179 else if (strcmp(ptr_arg, "string") == 0) {
5180 if (!*(args[cur_arg + 1])) {
5181 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5182 file, linenum, args[0], args[1], ptr_arg);
5183 err_code |= ERR_ALERT | ERR_FATAL;
5184 goto out;
5185 }
5186 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005187 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005188 curproxy->expect_str = strdup(args[cur_arg + 1]);
5189 }
5190 else if (strcmp(ptr_arg, "rstatus") == 0) {
5191 if (!*(args[cur_arg + 1])) {
5192 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5193 file, linenum, args[0], args[1], ptr_arg);
5194 err_code |= ERR_ALERT | ERR_FATAL;
5195 goto out;
5196 }
5197 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005198 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005199 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005200 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005201 free(curproxy->expect_regex);
5202 curproxy->expect_regex = NULL;
5203 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005204 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005205 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5206 error = NULL;
5207 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5208 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5209 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5210 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005211 err_code |= ERR_ALERT | ERR_FATAL;
5212 goto out;
5213 }
5214 }
5215 else if (strcmp(ptr_arg, "rstring") == 0) {
5216 if (!*(args[cur_arg + 1])) {
5217 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5218 file, linenum, args[0], args[1], ptr_arg);
5219 err_code |= ERR_ALERT | ERR_FATAL;
5220 goto out;
5221 }
5222 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005223 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005224 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005225 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005226 free(curproxy->expect_regex);
5227 curproxy->expect_regex = NULL;
5228 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005229 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005230 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5231 error = NULL;
5232 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5233 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5234 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5235 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005236 err_code |= ERR_ALERT | ERR_FATAL;
5237 goto out;
5238 }
5239 }
5240 else {
5241 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
5242 file, linenum, args[0], args[1], ptr_arg);
5243 err_code |= ERR_ALERT | ERR_FATAL;
5244 goto out;
5245 }
5246 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005247 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005248 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 +02005249 err_code |= ERR_ALERT | ERR_FATAL;
5250 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005251 }
5252 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005253 else if (!strcmp(args[0], "tcp-check")) {
5254 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5255 err_code |= ERR_WARN;
5256
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005257 if (strcmp(args[1], "comment") == 0) {
5258 int cur_arg;
5259 struct tcpcheck_rule *tcpcheck;
5260
5261 cur_arg = 1;
5262 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5263 tcpcheck->action = TCPCHK_ACT_COMMENT;
5264
5265 if (!*args[cur_arg + 1]) {
5266 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5267 file, linenum, args[cur_arg]);
5268 err_code |= ERR_ALERT | ERR_FATAL;
5269 goto out;
5270 }
5271
5272 tcpcheck->comment = strdup(args[cur_arg + 1]);
5273
5274 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
William Lallemanddf1425a2015-04-28 20:17:49 +02005275 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
5276 goto out;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005277 }
5278 else if (strcmp(args[1], "connect") == 0) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005279 const char *ptr_arg;
5280 int cur_arg;
5281 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005282
5283 /* check if first rule is also a 'connect' action */
Willy Tarreau5581c272015-05-13 12:24:53 +02005284 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
5285 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
5286 tcpcheck->action == TCPCHK_ACT_COMMENT) {
5287 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
5288 }
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005289
Willy Tarreau5581c272015-05-13 12:24:53 +02005290 if (&tcpcheck->list != &curproxy->tcpcheck_rules
5291 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
5292 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
5293 file, linenum);
5294 err_code |= ERR_ALERT | ERR_FATAL;
5295 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005296 }
5297
5298 cur_arg = 2;
5299 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5300 tcpcheck->action = TCPCHK_ACT_CONNECT;
5301
5302 /* parsing each parameters to fill up the rule */
5303 while (*(ptr_arg = args[cur_arg])) {
5304 /* tcp port */
5305 if (strcmp(args[cur_arg], "port") == 0) {
5306 if ( (atol(args[cur_arg + 1]) > 65535) ||
5307 (atol(args[cur_arg + 1]) < 1) ){
5308 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
5309 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
5310 err_code |= ERR_ALERT | ERR_FATAL;
5311 goto out;
5312 }
5313 tcpcheck->port = atol(args[cur_arg + 1]);
5314 cur_arg += 2;
5315 }
5316 /* send proxy protocol */
5317 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
5318 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
5319 cur_arg++;
5320 }
5321#ifdef USE_OPENSSL
5322 else if (strcmp(args[cur_arg], "ssl") == 0) {
5323 curproxy->options |= PR_O_TCPCHK_SSL;
5324 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
5325 cur_arg++;
5326 }
5327#endif /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005328 /* comment for this tcpcheck line */
5329 else if (strcmp(args[cur_arg], "comment") == 0) {
5330 if (!*args[cur_arg + 1]) {
5331 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5332 file, linenum, args[cur_arg]);
5333 err_code |= ERR_ALERT | ERR_FATAL;
5334 goto out;
5335 }
5336 tcpcheck->comment = strdup(args[cur_arg + 1]);
5337 cur_arg += 2;
5338 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005339 else {
5340#ifdef USE_OPENSSL
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005341 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 +01005342#else /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005343 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 +01005344#endif /* USE_OPENSSL */
5345 file, linenum, args[0], args[1], args[cur_arg]);
5346 err_code |= ERR_ALERT | ERR_FATAL;
5347 goto out;
5348 }
5349
5350 }
5351
5352 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5353 }
5354 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005355 if (! *(args[2]) ) {
5356 /* SEND string expected */
5357 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
5358 file, linenum, args[0], args[1], args[2]);
5359 err_code |= ERR_ALERT | ERR_FATAL;
5360 goto out;
5361 } else {
5362 struct tcpcheck_rule *tcpcheck;
5363
5364 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5365
5366 tcpcheck->action = TCPCHK_ACT_SEND;
5367 tcpcheck->string_len = strlen(args[2]);
5368 tcpcheck->string = strdup(args[2]);
5369 tcpcheck->expect_regex = NULL;
5370
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005371 /* comment for this tcpcheck line */
5372 if (strcmp(args[3], "comment") == 0) {
5373 if (!*args[4]) {
5374 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5375 file, linenum, args[3]);
5376 err_code |= ERR_ALERT | ERR_FATAL;
5377 goto out;
5378 }
5379 tcpcheck->comment = strdup(args[4]);
5380 }
5381
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005382 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5383 }
5384 }
5385 else if (strcmp(args[1], "send-binary") == 0) {
5386 if (! *(args[2]) ) {
5387 /* SEND binary string expected */
5388 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
5389 file, linenum, args[0], args[1], args[2]);
5390 err_code |= ERR_ALERT | ERR_FATAL;
5391 goto out;
5392 } else {
5393 struct tcpcheck_rule *tcpcheck;
5394 char *err = NULL;
5395
5396 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5397
5398 tcpcheck->action = TCPCHK_ACT_SEND;
5399 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5400 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5401 file, linenum, args[0], args[1], args[2], err);
5402 err_code |= ERR_ALERT | ERR_FATAL;
5403 goto out;
5404 }
5405 tcpcheck->expect_regex = NULL;
5406
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005407 /* comment for this tcpcheck line */
5408 if (strcmp(args[3], "comment") == 0) {
5409 if (!*args[4]) {
5410 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5411 file, linenum, args[3]);
5412 err_code |= ERR_ALERT | ERR_FATAL;
5413 goto out;
5414 }
5415 tcpcheck->comment = strdup(args[4]);
5416 }
5417
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005418 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5419 }
5420 }
5421 else if (strcmp(args[1], "expect") == 0) {
5422 const char *ptr_arg;
5423 int cur_arg;
5424 int inverse = 0;
5425
5426 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5427 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5428 err_code |= ERR_ALERT | ERR_FATAL;
5429 goto out;
5430 }
5431
5432 cur_arg = 2;
5433 /* consider exclamation marks, sole or at the beginning of a word */
5434 while (*(ptr_arg = args[cur_arg])) {
5435 while (*ptr_arg == '!') {
5436 inverse = !inverse;
5437 ptr_arg++;
5438 }
5439 if (*ptr_arg)
5440 break;
5441 cur_arg++;
5442 }
5443 /* now ptr_arg points to the beginning of a word past any possible
5444 * exclamation mark, and cur_arg is the argument which holds this word.
5445 */
5446 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005447 struct tcpcheck_rule *tcpcheck;
5448 char *err = NULL;
5449
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005450 if (!*(args[cur_arg + 1])) {
5451 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
5452 file, linenum, args[0], args[1], ptr_arg);
5453 err_code |= ERR_ALERT | ERR_FATAL;
5454 goto out;
5455 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005456
5457 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5458
5459 tcpcheck->action = TCPCHK_ACT_EXPECT;
5460 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5461 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5462 file, linenum, args[0], args[1], args[2], err);
5463 err_code |= ERR_ALERT | ERR_FATAL;
5464 goto out;
5465 }
5466 tcpcheck->expect_regex = NULL;
5467 tcpcheck->inverse = inverse;
5468
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005469 /* tcpcheck comment */
5470 cur_arg += 2;
5471 if (strcmp(args[cur_arg], "comment") == 0) {
5472 if (!*args[cur_arg + 1]) {
5473 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5474 file, linenum, args[cur_arg + 1]);
5475 err_code |= ERR_ALERT | ERR_FATAL;
5476 goto out;
5477 }
5478 tcpcheck->comment = strdup(args[cur_arg + 1]);
5479 }
5480
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005481 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5482 }
5483 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005484 struct tcpcheck_rule *tcpcheck;
5485
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005486 if (!*(args[cur_arg + 1])) {
5487 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5488 file, linenum, args[0], args[1], ptr_arg);
5489 err_code |= ERR_ALERT | ERR_FATAL;
5490 goto out;
5491 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005492
5493 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5494
5495 tcpcheck->action = TCPCHK_ACT_EXPECT;
5496 tcpcheck->string_len = strlen(args[cur_arg + 1]);
5497 tcpcheck->string = strdup(args[cur_arg + 1]);
5498 tcpcheck->expect_regex = NULL;
5499 tcpcheck->inverse = inverse;
5500
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005501 /* tcpcheck comment */
5502 cur_arg += 2;
5503 if (strcmp(args[cur_arg], "comment") == 0) {
5504 if (!*args[cur_arg + 1]) {
5505 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5506 file, linenum, args[cur_arg + 1]);
5507 err_code |= ERR_ALERT | ERR_FATAL;
5508 goto out;
5509 }
5510 tcpcheck->comment = strdup(args[cur_arg + 1]);
5511 }
5512
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005513 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5514 }
5515 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005516 struct tcpcheck_rule *tcpcheck;
5517
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005518 if (!*(args[cur_arg + 1])) {
5519 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5520 file, linenum, args[0], args[1], ptr_arg);
5521 err_code |= ERR_ALERT | ERR_FATAL;
5522 goto out;
5523 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005524
5525 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5526
5527 tcpcheck->action = TCPCHK_ACT_EXPECT;
5528 tcpcheck->string_len = 0;
5529 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005530 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
5531 error = NULL;
5532 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
5533 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5534 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5535 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005536 err_code |= ERR_ALERT | ERR_FATAL;
5537 goto out;
5538 }
5539 tcpcheck->inverse = inverse;
5540
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005541 /* tcpcheck comment */
5542 cur_arg += 2;
5543 if (strcmp(args[cur_arg], "comment") == 0) {
5544 if (!*args[cur_arg + 1]) {
5545 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5546 file, linenum, args[cur_arg + 1]);
5547 err_code |= ERR_ALERT | ERR_FATAL;
5548 goto out;
5549 }
5550 tcpcheck->comment = strdup(args[cur_arg + 1]);
5551 }
5552
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005553 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5554 }
5555 else {
5556 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
5557 file, linenum, args[0], args[1], ptr_arg);
5558 err_code |= ERR_ALERT | ERR_FATAL;
5559 goto out;
5560 }
5561 }
5562 else {
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005563 Alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005564 err_code |= ERR_ALERT | ERR_FATAL;
5565 goto out;
5566 }
5567 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01005568 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02005569 if (curproxy == &defproxy) {
5570 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005571 err_code |= ERR_ALERT | ERR_FATAL;
5572 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02005573 }
5574
Willy Tarreaub80c2302007-11-30 20:51:32 +01005575 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005576 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005577
5578 if (strcmp(args[1], "fail") == 0) {
5579 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01005580 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01005581 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
5582 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005583 err_code |= ERR_ALERT | ERR_FATAL;
5584 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005585 }
5586
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005587 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
5588 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
5589 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005590 err_code |= ERR_ALERT | ERR_FATAL;
5591 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005592 }
5593 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
5594 }
5595 else {
5596 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005597 err_code |= ERR_ALERT | ERR_FATAL;
5598 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005599 }
5600 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005601#ifdef TPROXY
5602 else if (!strcmp(args[0], "transparent")) {
5603 /* enable transparent proxy connections */
5604 curproxy->options |= PR_O_TRANSP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005605 if (alertif_too_many_args(0, file, linenum, args, &err_code))
5606 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005607 }
5608#endif
5609 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005610 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005611 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005612
Willy Tarreaubaaee002006-06-26 02:48:02 +02005613 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 Tarreaubaaee002006-06-26 02:48:02 +02005617 }
5618 curproxy->maxconn = 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 Tarreaubaaee002006-06-26 02:48:02 +02005621 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005622 else if (!strcmp(args[0], "backlog")) { /* backlog */
5623 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005624 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005625
5626 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 Tarreauc73ce2b2008-01-06 10:55:10 +01005630 }
5631 curproxy->backlog = 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 Tarreauc73ce2b2008-01-06 10:55:10 +01005634 }
Willy Tarreau86034312006-12-29 00:10:33 +01005635 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005636 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005637 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005638
Willy Tarreau86034312006-12-29 00:10:33 +01005639 if (*(args[1]) == 0) {
5640 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005641 err_code |= ERR_ALERT | ERR_FATAL;
5642 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005643 }
5644 curproxy->fullconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005645 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5646 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005647 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005648 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
5649 if (*(args[1]) == 0) {
5650 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005651 err_code |= ERR_ALERT | ERR_FATAL;
5652 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005653 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005654 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
5655 if (err) {
5656 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
5657 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02005658 err_code |= ERR_ALERT | ERR_FATAL;
5659 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005660 }
5661 curproxy->grace = val;
William Lallemanddf1425a2015-04-28 20:17:49 +02005662 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5663 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005664 }
5665 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01005666 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005667 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005668 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005669
Willy Tarreaubaaee002006-06-26 02:48:02 +02005670 if (curproxy == &defproxy) {
5671 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005672 err_code |= ERR_ALERT | ERR_FATAL;
5673 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005674 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005675 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005676 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005677
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02005678 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005679 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005680 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005681 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005682 goto out;
5683 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005684
5685 proto = protocol_by_family(sk->ss_family);
5686 if (!proto || !proto->connect) {
5687 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5688 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005689 err_code |= ERR_ALERT | ERR_FATAL;
5690 goto out;
5691 }
5692
5693 if (port1 != port2) {
5694 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5695 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005696 err_code |= ERR_ALERT | ERR_FATAL;
5697 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005698 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005699
5700 if (!port1) {
5701 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5702 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005703 err_code |= ERR_ALERT | ERR_FATAL;
5704 goto out;
5705 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005706
William Lallemanddf1425a2015-04-28 20:17:49 +02005707 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5708 goto out;
5709
Willy Tarreaud5191e72010-02-09 20:50:45 +01005710 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005711 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005712 }
5713 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005714 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005715 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005716
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005717 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5718 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005719 err_code |= ERR_ALERT | ERR_FATAL;
5720 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005721 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005722 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005723 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005724 /**
5725 * The syntax for hash-type config element is
5726 * hash-type {map-based|consistent} [[<algo>] avalanche]
5727 *
5728 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5729 */
5730 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005731
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005732 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5733 err_code |= ERR_WARN;
5734
5735 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005736 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5737 }
5738 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005739 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5740 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005741 else if (strcmp(args[1], "avalanche") == 0) {
5742 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]);
5743 err_code |= ERR_ALERT | ERR_FATAL;
5744 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005745 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005746 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005747 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005748 err_code |= ERR_ALERT | ERR_FATAL;
5749 goto out;
5750 }
Bhaskar98634f02013-10-29 23:30:51 -04005751
5752 /* set the hash function to use */
5753 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005754 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005755 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005756
5757 /* if consistent with no argument, then avalanche modifier is also applied */
5758 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5759 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005760 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005761 /* set the hash function */
5762 if (!strcmp(args[2], "sdbm")) {
5763 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5764 }
5765 else if (!strcmp(args[2], "djb2")) {
5766 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005767 }
5768 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005769 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005770 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005771 else if (!strcmp(args[2], "crc32")) {
5772 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5773 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005774 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005775 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 -05005776 err_code |= ERR_ALERT | ERR_FATAL;
5777 goto out;
5778 }
5779
5780 /* set the hash modifier */
5781 if (!strcmp(args[3], "avalanche")) {
5782 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5783 }
5784 else if (*args[3]) {
5785 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5786 err_code |= ERR_ALERT | ERR_FATAL;
5787 goto out;
5788 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005789 }
William Lallemanda73203e2012-03-12 12:48:57 +01005790 }
William Lallemanda73203e2012-03-12 12:48:57 +01005791 else if (strcmp(args[0], "unique-id-format") == 0) {
5792 if (!*(args[1])) {
5793 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5794 err_code |= ERR_ALERT | ERR_FATAL;
5795 goto out;
5796 }
William Lallemand3203ff42012-11-11 17:30:56 +01005797 if (*(args[2])) {
5798 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5799 err_code |= ERR_ALERT | ERR_FATAL;
5800 goto out;
5801 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005802 free(curproxy->conf.uniqueid_format_string);
5803 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005804
Willy Tarreau62a61232013-04-12 18:13:46 +02005805 free(curproxy->conf.uif_file);
5806 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5807 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005808 }
William Lallemanda73203e2012-03-12 12:48:57 +01005809
5810 else if (strcmp(args[0], "unique-id-header") == 0) {
5811 if (!*(args[1])) {
5812 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5813 err_code |= ERR_ALERT | ERR_FATAL;
5814 goto out;
5815 }
5816 free(curproxy->header_unique_id);
5817 curproxy->header_unique_id = strdup(args[1]);
5818 }
5819
William Lallemand723b73a2012-02-08 16:37:49 +01005820 else if (strcmp(args[0], "log-format") == 0) {
5821 if (!*(args[1])) {
5822 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5823 err_code |= ERR_ALERT | ERR_FATAL;
5824 goto out;
5825 }
William Lallemand3203ff42012-11-11 17:30:56 +01005826 if (*(args[2])) {
5827 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5828 err_code |= ERR_ALERT | ERR_FATAL;
5829 goto out;
5830 }
Willy Tarreau196729e2012-05-31 19:30:26 +02005831
Willy Tarreau62a61232013-04-12 18:13:46 +02005832 if (curproxy->conf.logformat_string != default_http_log_format &&
5833 curproxy->conf.logformat_string != default_tcp_log_format &&
5834 curproxy->conf.logformat_string != clf_http_log_format)
5835 free(curproxy->conf.logformat_string);
5836 curproxy->conf.logformat_string = strdup(args[1]);
5837
5838 free(curproxy->conf.lfs_file);
5839 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5840 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005841
5842 /* get a chance to improve log-format error reporting by
5843 * reporting the correct line-number when possible.
5844 */
5845 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5846 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5847 file, linenum, curproxy->id);
5848 err_code |= ERR_WARN;
5849 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005850 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02005851 else if (!strcmp(args[0], "log-format-sd")) {
5852 if (!*(args[1])) {
5853 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5854 err_code |= ERR_ALERT | ERR_FATAL;
5855 goto out;
5856 }
5857 if (*(args[2])) {
5858 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5859 err_code |= ERR_ALERT | ERR_FATAL;
5860 goto out;
5861 }
5862
5863 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
5864 free(curproxy->conf.logformat_sd_string);
5865 curproxy->conf.logformat_sd_string = strdup(args[1]);
5866
5867 free(curproxy->conf.lfsd_file);
5868 curproxy->conf.lfsd_file = strdup(curproxy->conf.args.file);
5869 curproxy->conf.lfsd_line = curproxy->conf.args.line;
5870
5871 /* get a chance to improve log-format-sd error reporting by
5872 * reporting the correct line-number when possible.
5873 */
5874 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5875 Warning("parsing [%s:%d] : backend '%s' : 'log-format-sd' directive is ignored in backends.\n",
5876 file, linenum, curproxy->id);
5877 err_code |= ERR_WARN;
5878 }
5879 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01005880 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
5881 if (*(args[1]) == 0) {
5882 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
5883 err_code |= ERR_ALERT | ERR_FATAL;
5884 goto out;
5885 }
Dragan Dosen43885c72015-10-01 13:18:13 +02005886 chunk_destroy(&curproxy->log_tag);
5887 chunk_initstr(&curproxy->log_tag, strdup(args[1]));
Willy Tarreau094af4e2015-01-07 15:03:42 +01005888 }
William Lallemand0f99e342011-10-12 17:50:54 +02005889 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
5890 /* delete previous herited or defined syslog servers */
5891 struct logsrv *back;
5892
5893 if (*(args[1]) != 0) {
5894 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
5895 err_code |= ERR_ALERT | ERR_FATAL;
5896 goto out;
5897 }
5898
William Lallemand723b73a2012-02-08 16:37:49 +01005899 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
5900 LIST_DEL(&tmplogsrv->list);
5901 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02005902 }
5903 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005904 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02005905 struct logsrv *logsrv;
5906
Willy Tarreaubaaee002006-06-26 02:48:02 +02005907 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005908 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01005909 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02005910 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01005911 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02005912 LIST_INIT(&node->list);
5913 LIST_ADDQ(&curproxy->logsrvs, &node->list);
5914 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005915 }
5916 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005917 struct sockaddr_storage *sk;
5918 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02005919 int arg = 0;
5920 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02005921
5922 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005923
Willy Tarreau18324f52014-06-27 18:10:07 +02005924 /* just after the address, a length may be specified */
5925 if (strcmp(args[arg+2], "len") == 0) {
5926 len = atoi(args[arg+3]);
5927 if (len < 80 || len > 65535) {
5928 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
5929 file, linenum, args[arg+3]);
5930 err_code |= ERR_ALERT | ERR_FATAL;
5931 goto out;
5932 }
5933 logsrv->maxlen = len;
5934
5935 /* skip these two args */
5936 arg += 2;
5937 }
5938 else
5939 logsrv->maxlen = MAX_SYSLOG_LEN;
5940
5941 if (logsrv->maxlen > global.max_syslog_len) {
5942 global.max_syslog_len = logsrv->maxlen;
Dragan Dosen59cee972015-09-19 22:09:02 +02005943 logheader = realloc(logheader, global.max_syslog_len + 1);
Dragan Dosen1322d092015-09-22 16:05:32 +02005944 logheader_rfc5424 = realloc(logheader_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02005945 logline = realloc(logline, global.max_syslog_len + 1);
Dragan Dosen0b85ece2015-09-25 19:17:44 +02005946 logline_rfc5424 = realloc(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02005947 }
5948
Dragan Dosen1322d092015-09-22 16:05:32 +02005949 /* after the length, a format may be specified */
5950 if (strcmp(args[arg+2], "format") == 0) {
5951 logsrv->format = get_log_format(args[arg+3]);
5952 if (logsrv->format < 0) {
5953 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
5954 err_code |= ERR_ALERT | ERR_FATAL;
5955 goto out;
5956 }
5957
5958 /* skip these two args */
5959 arg += 2;
5960 }
5961
William Lallemanddf1425a2015-04-28 20:17:49 +02005962 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
5963 goto out;
5964
Willy Tarreau18324f52014-06-27 18:10:07 +02005965 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005966 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005967 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005968 err_code |= ERR_ALERT | ERR_FATAL;
5969 goto out;
5970
Willy Tarreaubaaee002006-06-26 02:48:02 +02005971 }
5972
William Lallemand0f99e342011-10-12 17:50:54 +02005973 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02005974 if (*(args[arg+3])) {
5975 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005976 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005977 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005978 err_code |= ERR_ALERT | ERR_FATAL;
5979 goto out;
5980
Willy Tarreaubaaee002006-06-26 02:48:02 +02005981 }
5982 }
5983
William Lallemand0f99e342011-10-12 17:50:54 +02005984 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02005985 if (*(args[arg+4])) {
5986 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01005987 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005988 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02005989 err_code |= ERR_ALERT | ERR_FATAL;
5990 goto out;
5991
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005992 }
5993 }
5994
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02005995 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005996 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005997 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005998 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005999 goto out;
6000 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006001
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006002 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006003
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006004 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006005 if (port1 != port2) {
6006 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6007 file, linenum, args[0], args[1]);
6008 err_code |= ERR_ALERT | ERR_FATAL;
6009 goto out;
6010 }
6011
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006012 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02006013 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006014 }
William Lallemand0f99e342011-10-12 17:50:54 +02006015
6016 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006017 }
6018 else {
6019 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
6020 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02006021 err_code |= ERR_ALERT | ERR_FATAL;
6022 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006023 }
6024 }
6025 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006026 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006027 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01006028 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006029 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006030
Willy Tarreau977b8e42006-12-29 14:19:17 +01006031 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006032 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006033
Willy Tarreaubaaee002006-06-26 02:48:02 +02006034 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006035 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
6036 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02006037 err_code |= ERR_ALERT | ERR_FATAL;
6038 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006039 }
Willy Tarreau368480c2009-03-01 08:27:21 +01006040
6041 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01006042 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6043 free(curproxy->conn_src.iface_name);
6044 curproxy->conn_src.iface_name = NULL;
6045 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01006046
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006047 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006048 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006049 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006050 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006051 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006052 goto out;
6053 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006054
6055 proto = protocol_by_family(sk->ss_family);
6056 if (!proto || !proto->connect) {
6057 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006058 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006059 err_code |= ERR_ALERT | ERR_FATAL;
6060 goto out;
6061 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006062
6063 if (port1 != port2) {
6064 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6065 file, linenum, args[0], args[1]);
6066 err_code |= ERR_ALERT | ERR_FATAL;
6067 goto out;
6068 }
6069
Willy Tarreauef9a3602012-12-08 22:29:20 +01006070 curproxy->conn_src.source_addr = *sk;
6071 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006072
6073 cur_arg = 2;
6074 while (*(args[cur_arg])) {
6075 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau29fbe512015-08-20 19:35:14 +02006076#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006077 if (!*args[cur_arg + 1]) {
6078 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
6079 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006080 err_code |= ERR_ALERT | ERR_FATAL;
6081 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006082 }
6083
6084 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006085 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6086 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006087 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006088 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6089 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02006090 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
6091 char *name, *end;
6092
6093 name = args[cur_arg+1] + 7;
6094 while (isspace(*name))
6095 name++;
6096
6097 end = name;
6098 while (*end && !isspace(*end) && *end != ',' && *end != ')')
6099 end++;
6100
Willy Tarreauef9a3602012-12-08 22:29:20 +01006101 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6102 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
6103 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
6104 curproxy->conn_src.bind_hdr_len = end - name;
6105 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
6106 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
6107 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02006108
6109 /* now look for an occurrence number */
6110 while (isspace(*end))
6111 end++;
6112 if (*end == ',') {
6113 end++;
6114 name = end;
6115 if (*end == '-')
6116 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01006117 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02006118 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01006119 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006120 }
6121
Willy Tarreauef9a3602012-12-08 22:29:20 +01006122 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02006123 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
6124 " occurrences values smaller than %d.\n",
6125 file, linenum, MAX_HDR_HISTORY);
6126 err_code |= ERR_ALERT | ERR_FATAL;
6127 goto out;
6128 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006129 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01006130 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006131
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006132 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006133 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006134 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006135 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006136 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006137 goto out;
6138 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006139
6140 proto = protocol_by_family(sk->ss_family);
6141 if (!proto || !proto->connect) {
6142 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
6143 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006144 err_code |= ERR_ALERT | ERR_FATAL;
6145 goto out;
6146 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006147
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006148 if (port1 != port2) {
6149 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6150 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006151 err_code |= ERR_ALERT | ERR_FATAL;
6152 goto out;
6153 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006154 curproxy->conn_src.tproxy_addr = *sk;
6155 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006156 }
6157 global.last_checks |= LSTCHK_NETADM;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006158#else /* no TPROXY support */
6159 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01006160 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006161 err_code |= ERR_ALERT | ERR_FATAL;
6162 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006163#endif
6164 cur_arg += 2;
6165 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01006166 }
6167
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006168 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
6169#ifdef SO_BINDTODEVICE
6170 if (!*args[cur_arg + 1]) {
6171 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
6172 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006173 err_code |= ERR_ALERT | ERR_FATAL;
6174 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006175 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006176 free(curproxy->conn_src.iface_name);
6177 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
6178 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006179 global.last_checks |= LSTCHK_NETADM;
6180#else
6181 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
6182 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02006183 err_code |= ERR_ALERT | ERR_FATAL;
6184 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01006185#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006186 cur_arg += 2;
6187 continue;
6188 }
6189 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02006190 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006191 err_code |= ERR_ALERT | ERR_FATAL;
6192 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006193 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006194 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006195 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
6196 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
6197 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02006198 err_code |= ERR_ALERT | ERR_FATAL;
6199 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006200 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006201 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006202 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006203 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6204 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006205 err_code |= ERR_ALERT | ERR_FATAL;
6206 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006207 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006208
6209 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006210 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006211 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006212 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006213 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006214 }
6215 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006216 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006217 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006218 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006219 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006220 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006221 }
6222 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006223 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006224 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006225 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006226 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006227 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006228 }
6229 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006230 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006231 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006232 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006233 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006234 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006235 }
6236 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006237 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006238 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006239 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006240 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006241 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006242 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006243 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006244 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006245 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006246 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006247 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006248 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006249 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006250 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006251 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006252 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6253 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006254 err_code |= ERR_ALERT | ERR_FATAL;
6255 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006256 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006257
6258 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006259 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006260 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006261 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006262 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006263 }
6264 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006265 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006266 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006267 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006268 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006269 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006270 }
6271 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006272 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006273 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006274 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006275 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006276 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006277 }
6278 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006279 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006280 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006281 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006282 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006283 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006284 }
6285 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006286 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006287 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006288 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006289 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006290 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006291 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006292 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006293 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006294 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006295 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006296 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006297 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006298 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006299 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006300 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006301
Willy Tarreaubaaee002006-06-26 02:48:02 +02006302 if (curproxy == &defproxy) {
6303 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006304 err_code |= ERR_ALERT | ERR_FATAL;
6305 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006306 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006307 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006308 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006309
Willy Tarreaubaaee002006-06-26 02:48:02 +02006310 if (*(args[1]) == 0) {
6311 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006312 err_code |= ERR_ALERT | ERR_FATAL;
6313 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006314 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006315
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006316 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006317 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6318 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6319 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006320 err_code |= ERR_ALERT | ERR_FATAL;
6321 goto out;
6322 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006323 err_code |= warnif_cond_conflicts(cond,
6324 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6325 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006326 }
6327 else if (*args[2]) {
6328 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6329 file, linenum, args[0], args[2]);
6330 err_code |= ERR_ALERT | ERR_FATAL;
6331 goto out;
6332 }
6333
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006334 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006335 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006336 wl->s = strdup(args[1]);
6337 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02006338 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006339 }
6340 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006341 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006342 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6343 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006344 err_code |= ERR_ALERT | ERR_FATAL;
6345 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006346 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006347
Willy Tarreauade5ec42010-01-28 19:33:49 +01006348 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006349 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006350 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006351 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006352 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006353 }
6354 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006355 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006356 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006357 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006358 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006359 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006360 }
6361 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006362 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006363 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006364 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006365 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006366 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006367 }
6368 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006369 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006370 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6371 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006372 err_code |= ERR_ALERT | ERR_FATAL;
6373 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006374 }
6375
Willy Tarreauade5ec42010-01-28 19:33:49 +01006376 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006377 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006378 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006379 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006380 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006381 }
6382 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006383 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006384 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006385 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006386 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006387 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006388 }
6389 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006390 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006391 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006392 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006393 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006394 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006395 }
6396 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006397 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006398
Willy Tarreaubaaee002006-06-26 02:48:02 +02006399 if (curproxy == &defproxy) {
6400 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006401 err_code |= ERR_ALERT | ERR_FATAL;
6402 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006403 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006404 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006405 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006406
Willy Tarreaubaaee002006-06-26 02:48:02 +02006407 if (*(args[1]) == 0) {
6408 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006409 err_code |= ERR_ALERT | ERR_FATAL;
6410 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006411 }
6412
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006413 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006414 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6415 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6416 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006417 err_code |= ERR_ALERT | ERR_FATAL;
6418 goto out;
6419 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006420 err_code |= warnif_cond_conflicts(cond,
6421 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
6422 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006423 }
6424 else if (*args[2]) {
6425 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6426 file, linenum, args[0], args[2]);
6427 err_code |= ERR_ALERT | ERR_FATAL;
6428 goto out;
6429 }
6430
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006431 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006432 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006433 wl->s = strdup(args[1]);
6434 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006435 }
6436 else if (!strcmp(args[0], "errorloc") ||
6437 !strcmp(args[0], "errorloc302") ||
6438 !strcmp(args[0], "errorloc303")) { /* error location */
6439 int errnum, errlen;
6440 char *err;
6441
Willy Tarreau977b8e42006-12-29 14:19:17 +01006442 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006443 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006444
Willy Tarreaubaaee002006-06-26 02:48:02 +02006445 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006446 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006447 err_code |= ERR_ALERT | ERR_FATAL;
6448 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006449 }
6450
6451 errnum = atol(args[1]);
6452 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006453 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
6454 err = malloc(errlen);
6455 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006456 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006457 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
6458 err = malloc(errlen);
6459 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006460 }
6461
Willy Tarreau0f772532006-12-23 20:51:41 +01006462 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6463 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006464 chunk_destroy(&curproxy->errmsg[rc]);
6465 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01006466 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006467 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006468 }
Willy Tarreau0f772532006-12-23 20:51:41 +01006469
6470 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006471 Warning("parsing [%s:%d] : status code %d not handled by '%s', error relocation will be ignored.\n",
6472 file, linenum, errnum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006473 free(err);
6474 }
6475 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02006476 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
6477 int errnum, errlen, fd;
6478 char *err;
6479 struct stat stat;
6480
6481 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006482 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006483
6484 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006485 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006486 err_code |= ERR_ALERT | ERR_FATAL;
6487 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006488 }
6489
6490 fd = open(args[2], O_RDONLY);
6491 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
6492 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
6493 file, linenum, args[2], args[1]);
6494 if (fd >= 0)
6495 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02006496 err_code |= ERR_ALERT | ERR_FATAL;
6497 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006498 }
6499
Willy Tarreau27a674e2009-08-17 07:23:33 +02006500 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02006501 errlen = stat.st_size;
6502 } else {
6503 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02006504 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02006505 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02006506 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006507 }
6508
6509 err = malloc(errlen); /* malloc() must succeed during parsing */
6510 errnum = read(fd, err, errlen);
6511 if (errnum != errlen) {
6512 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
6513 file, linenum, args[2], args[1]);
6514 close(fd);
6515 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02006516 err_code |= ERR_ALERT | ERR_FATAL;
6517 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006518 }
6519 close(fd);
6520
6521 errnum = atol(args[1]);
6522 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6523 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006524 chunk_destroy(&curproxy->errmsg[rc]);
6525 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02006526 break;
6527 }
6528 }
6529
6530 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006531 Warning("parsing [%s:%d] : status code %d not handled by '%s', error customization will be ignored.\n",
6532 file, linenum, errnum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006533 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006534 free(err);
6535 }
6536 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006537 else if (!strcmp(args[0], "compression")) {
6538 struct comp *comp;
6539 if (curproxy->comp == NULL) {
6540 comp = calloc(1, sizeof(struct comp));
6541 curproxy->comp = comp;
6542 } else {
6543 comp = curproxy->comp;
6544 }
6545
6546 if (!strcmp(args[1], "algo")) {
6547 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01006548 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01006549
William Lallemand82fe75c2012-10-23 10:25:10 +02006550 cur_arg = 2;
6551 if (!*args[cur_arg]) {
6552 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
6553 file, linenum, args[0]);
6554 err_code |= ERR_ALERT | ERR_FATAL;
6555 goto out;
6556 }
6557 while (*(args[cur_arg])) {
6558 if (comp_append_algo(comp, args[cur_arg]) < 0) {
6559 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
6560 file, linenum, args[0], args[cur_arg]);
6561 err_code |= ERR_ALERT | ERR_FATAL;
6562 goto out;
6563 }
William Lallemand552df672012-11-07 13:21:47 +01006564 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
6565 curproxy->comp->algos->end(&ctx);
6566 } else {
6567 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
6568 file, linenum, args[0], args[cur_arg]);
6569 err_code |= ERR_ALERT | ERR_FATAL;
6570 goto out;
6571 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006572 cur_arg ++;
6573 continue;
6574 }
6575 }
Willy Tarreau70737d12012-10-27 00:34:28 +02006576 else if (!strcmp(args[1], "offload")) {
6577 comp->offload = 1;
6578 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006579 else if (!strcmp(args[1], "type")) {
6580 int cur_arg;
6581 cur_arg = 2;
6582 if (!*args[cur_arg]) {
6583 Alert("parsing [%s:%d] : '%s' expects <type>\n",
6584 file, linenum, args[0]);
6585 err_code |= ERR_ALERT | ERR_FATAL;
6586 goto out;
6587 }
6588 while (*(args[cur_arg])) {
6589 comp_append_type(comp, args[cur_arg]);
6590 cur_arg ++;
6591 continue;
6592 }
6593 }
6594 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02006595 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02006596 file, linenum, args[0]);
6597 err_code |= ERR_ALERT | ERR_FATAL;
6598 goto out;
6599 }
6600 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006601 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006602 struct cfg_kw_list *kwl;
6603 int index;
6604
6605 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6606 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6607 if (kwl->kw[index].section != CFG_LISTEN)
6608 continue;
6609 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6610 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006611 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006612 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006613 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006614 err_code |= ERR_ALERT | ERR_FATAL;
6615 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006616 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006617 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006618 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006619 err_code |= ERR_WARN;
6620 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006621 }
Willy Tarreau93893792009-07-23 13:19:11 +02006622 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006623 }
6624 }
6625 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006626
Willy Tarreau6daf3432008-01-22 16:44:08 +01006627 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006628 err_code |= ERR_ALERT | ERR_FATAL;
6629 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006630 }
Willy Tarreau93893792009-07-23 13:19:11 +02006631 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006632 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006633 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006634}
6635
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006636int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006637cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
6638{
6639#ifdef CONFIG_HAP_NS
6640 const char *err;
6641 const char *item = args[0];
6642
6643 if (!strcmp(item, "namespace_list")) {
6644 return 0;
6645 }
6646 else if (!strcmp(item, "namespace")) {
6647 size_t idx = 1;
6648 const char *current;
6649 while (*(current = args[idx++])) {
6650 err = invalid_char(current);
6651 if (err) {
6652 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6653 file, linenum, *err, item, current);
6654 return ERR_ALERT | ERR_FATAL;
6655 }
6656
6657 if (netns_store_lookup(current, strlen(current))) {
6658 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
6659 file, linenum, current);
6660 return ERR_ALERT | ERR_FATAL;
6661 }
6662 if (!netns_store_insert(current)) {
6663 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
6664 file, linenum, current);
6665 return ERR_ALERT | ERR_FATAL;
6666 }
6667 }
6668 }
6669
6670 return 0;
6671#else
6672 Alert("parsing [%s:%d]: namespace support is not compiled in.",
6673 file, linenum);
6674 return ERR_ALERT | ERR_FATAL;
6675#endif
6676}
6677
6678int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006679cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6680{
6681
6682 int err_code = 0;
6683 const char *err;
6684
6685 if (!strcmp(args[0], "userlist")) { /* new userlist */
6686 struct userlist *newul;
6687
6688 if (!*args[1]) {
6689 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6690 file, linenum, args[0]);
6691 err_code |= ERR_ALERT | ERR_FATAL;
6692 goto out;
6693 }
William Lallemand6e62fb62015-04-28 16:55:23 +02006694 if (alertif_too_many_args(1, file, linenum, args, &err_code))
6695 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006696
6697 err = invalid_char(args[1]);
6698 if (err) {
6699 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6700 file, linenum, *err, args[0], args[1]);
6701 err_code |= ERR_ALERT | ERR_FATAL;
6702 goto out;
6703 }
6704
6705 for (newul = userlist; newul; newul = newul->next)
6706 if (!strcmp(newul->name, args[1])) {
6707 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6708 file, linenum, args[1]);
6709 err_code |= ERR_WARN;
6710 goto out;
6711 }
6712
6713 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
6714 if (!newul) {
6715 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6716 err_code |= ERR_ALERT | ERR_ABORT;
6717 goto out;
6718 }
6719
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006720 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006721 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006722 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6723 err_code |= ERR_ALERT | ERR_ABORT;
6724 goto out;
6725 }
6726
6727 newul->next = userlist;
6728 userlist = newul;
6729
6730 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006731 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006732 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006733 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006734
6735 if (!*args[1]) {
6736 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6737 file, linenum, args[0]);
6738 err_code |= ERR_ALERT | ERR_FATAL;
6739 goto out;
6740 }
6741
6742 err = invalid_char(args[1]);
6743 if (err) {
6744 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6745 file, linenum, *err, args[0], args[1]);
6746 err_code |= ERR_ALERT | ERR_FATAL;
6747 goto out;
6748 }
6749
William Lallemand4ac9f542015-05-28 18:03:51 +02006750 if (!userlist)
6751 goto out;
6752
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006753 for (ag = userlist->groups; ag; ag = ag->next)
6754 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006755 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6756 file, linenum, args[1], userlist->name);
6757 err_code |= ERR_ALERT;
6758 goto out;
6759 }
6760
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006761 ag = calloc(1, sizeof(*ag));
6762 if (!ag) {
6763 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6764 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006765 goto out;
6766 }
6767
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006768 ag->name = strdup(args[1]);
6769 if (!ag) {
6770 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6771 err_code |= ERR_ALERT | ERR_ABORT;
6772 goto out;
6773 }
6774
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006775 cur_arg = 2;
6776
6777 while (*args[cur_arg]) {
6778 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006779 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006780 cur_arg += 2;
6781 continue;
6782 } else {
6783 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6784 file, linenum, args[0]);
6785 err_code |= ERR_ALERT | ERR_FATAL;
6786 goto out;
6787 }
6788 }
6789
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006790 ag->next = userlist->groups;
6791 userlist->groups = ag;
6792
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006793 } else if (!strcmp(args[0], "user")) { /* new user */
6794 struct auth_users *newuser;
6795 int cur_arg;
6796
6797 if (!*args[1]) {
6798 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6799 file, linenum, args[0]);
6800 err_code |= ERR_ALERT | ERR_FATAL;
6801 goto out;
6802 }
William Lallemand4ac9f542015-05-28 18:03:51 +02006803 if (!userlist)
6804 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006805
6806 for (newuser = userlist->users; newuser; newuser = newuser->next)
6807 if (!strcmp(newuser->user, args[1])) {
6808 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6809 file, linenum, args[1], userlist->name);
6810 err_code |= ERR_ALERT;
6811 goto out;
6812 }
6813
6814 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
6815 if (!newuser) {
6816 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6817 err_code |= ERR_ALERT | ERR_ABORT;
6818 goto out;
6819 }
6820
6821 newuser->user = strdup(args[1]);
6822
6823 newuser->next = userlist->users;
6824 userlist->users = newuser;
6825
6826 cur_arg = 2;
6827
6828 while (*args[cur_arg]) {
6829 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006830#ifdef CONFIG_HAP_CRYPT
6831 if (!crypt("", args[cur_arg + 1])) {
6832 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6833 file, linenum, newuser->user);
6834 err_code |= ERR_ALERT | ERR_FATAL;
6835 goto out;
6836 }
6837#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006838 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6839 file, linenum);
6840 err_code |= ERR_ALERT;
6841#endif
6842 newuser->pass = strdup(args[cur_arg + 1]);
6843 cur_arg += 2;
6844 continue;
6845 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6846 newuser->pass = strdup(args[cur_arg + 1]);
6847 newuser->flags |= AU_O_INSECURE;
6848 cur_arg += 2;
6849 continue;
6850 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006851 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006852 cur_arg += 2;
6853 continue;
6854 } else {
6855 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6856 file, linenum, args[0]);
6857 err_code |= ERR_ALERT | ERR_FATAL;
6858 goto out;
6859 }
6860 }
6861 } else {
6862 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6863 err_code |= ERR_ALERT | ERR_FATAL;
6864 }
6865
6866out:
6867 return err_code;
6868}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006869
6870/*
6871 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006872 * Returns the error code, 0 if OK, or any combination of :
6873 * - ERR_ABORT: must abort ASAP
6874 * - ERR_FATAL: we can continue parsing but not start the service
6875 * - ERR_WARN: a warning has been emitted
6876 * - ERR_ALERT: an alert has been emitted
6877 * Only the two first ones can stop processing, the two others are just
6878 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006879 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006880int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006881{
William Lallemand64e84512015-05-12 14:25:37 +02006882 char *thisline;
6883 int linesize = LINESIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006884 FILE *f;
6885 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02006886 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006887 struct cfg_section *cs = NULL;
6888 struct cfg_section *ics;
William Lallemand64e84512015-05-12 14:25:37 +02006889 int readbytes = 0;
6890
6891 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
William Lallemandb2f07452015-05-12 14:27:13 +02006892 Alert("parsing [%s] : out of memory.\n", file);
William Lallemand64e84512015-05-12 14:25:37 +02006893 return -1;
6894 }
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006895
6896 /* Register internal sections */
6897 if (!cfg_register_section("listen", cfg_parse_listen) ||
6898 !cfg_register_section("frontend", cfg_parse_listen) ||
6899 !cfg_register_section("backend", cfg_parse_listen) ||
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006900 !cfg_register_section("defaults", cfg_parse_listen) ||
6901 !cfg_register_section("global", cfg_parse_global) ||
6902 !cfg_register_section("userlist", cfg_parse_users) ||
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006903 !cfg_register_section("peers", cfg_parse_peers) ||
Simon Horman0d16a402015-01-30 11:22:58 +09006904 !cfg_register_section("mailers", cfg_parse_mailers) ||
Baptiste Assmann325137d2015-04-13 23:40:55 +02006905 !cfg_register_section("namespace_list", cfg_parse_netns) ||
6906 !cfg_register_section("resolvers", cfg_parse_resolvers))
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006907 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006908
Willy Tarreaubaaee002006-06-26 02:48:02 +02006909 if ((f=fopen(file,"r")) == NULL)
6910 return -1;
6911
William Lallemandb2f07452015-05-12 14:27:13 +02006912next_line:
William Lallemand64e84512015-05-12 14:25:37 +02006913 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02006914 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006915 char *end;
6916 char *args[MAX_LINE_ARGS + 1];
6917 char *line = thisline;
William Lallemandf9873ba2015-05-05 17:37:14 +02006918 int dquote = 0; /* double quote */
6919 int squote = 0; /* simple quote */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006920
Willy Tarreaubaaee002006-06-26 02:48:02 +02006921 linenum++;
6922
6923 end = line + strlen(line);
6924
William Lallemand64e84512015-05-12 14:25:37 +02006925 if (end-line == linesize-1 && *(end-1) != '\n') {
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006926 /* Check if we reached the limit and the last char is not \n.
6927 * Watch out for the last line without the terminating '\n'!
6928 */
William Lallemand64e84512015-05-12 14:25:37 +02006929 char *newline;
6930 int newlinesize = linesize * 2;
6931
6932 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
6933 if (newline == NULL) {
6934 Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
6935 file, linenum);
6936 err_code |= ERR_ALERT | ERR_FATAL;
6937 continue;
6938 }
6939
6940 readbytes = linesize - 1;
6941 linesize = newlinesize;
6942 thisline = newline;
6943 continue;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006944 }
6945
William Lallemand64e84512015-05-12 14:25:37 +02006946 readbytes = 0;
6947
Willy Tarreaubaaee002006-06-26 02:48:02 +02006948 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006949 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006950 line++;
William Lallemandf9873ba2015-05-05 17:37:14 +02006951
Willy Tarreaubaaee002006-06-26 02:48:02 +02006952 arg = 0;
6953 args[arg] = line;
6954
6955 while (*line && arg < MAX_LINE_ARGS) {
William Lallemandf9873ba2015-05-05 17:37:14 +02006956 if (*line == '"' && !squote) { /* double quote outside single quotes */
6957 if (dquote)
6958 dquote = 0;
6959 else
6960 dquote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02006961 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02006962 end--;
6963 }
6964 else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
6965 if (squote)
6966 squote = 0;
6967 else
6968 squote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02006969 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02006970 end--;
6971 }
6972 else if (*line == '\\' && !squote) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006973 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
6974 * C equivalent value. Other combinations left unchanged (eg: \1).
6975 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006976 int skip = 0;
6977 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
6978 *line = line[1];
6979 skip = 1;
6980 }
6981 else if (line[1] == 'r') {
6982 *line = '\r';
6983 skip = 1;
William Lallemandf9873ba2015-05-05 17:37:14 +02006984 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006985 else if (line[1] == 'n') {
6986 *line = '\n';
6987 skip = 1;
6988 }
6989 else if (line[1] == 't') {
6990 *line = '\t';
6991 skip = 1;
6992 }
6993 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01006994 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006995 unsigned char hex1, hex2;
6996 hex1 = toupper(line[2]) - '0';
6997 hex2 = toupper(line[3]) - '0';
6998 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
6999 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
7000 *line = (hex1<<4) + hex2;
7001 skip = 3;
7002 }
7003 else {
7004 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007005 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007006 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007007 } else if (line[1] == '"') {
7008 *line = '"';
7009 skip = 1;
7010 } else if (line[1] == '\'') {
7011 *line = '\'';
7012 skip = 1;
William Lallemandb2f07452015-05-12 14:27:13 +02007013 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
7014 *line = '$';
7015 skip = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007016 }
7017 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01007018 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02007019 end -= skip;
7020 }
7021 line++;
7022 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007023 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007024 /* end of string, end of loop */
7025 *line = 0;
7026 break;
7027 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007028 else if (!squote && !dquote && isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007029 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007030 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007031 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007032 line++;
7033 args[++arg] = line;
7034 }
William Lallemandb2f07452015-05-12 14:27:13 +02007035 else if (dquote && *line == '$') {
7036 /* environment variables are evaluated inside double quotes */
7037 char *var_beg;
7038 char *var_end;
7039 char save_char;
7040 char *value;
7041 int val_len;
7042 int newlinesize;
7043 int braces = 0;
7044
7045 var_beg = line + 1;
7046 var_end = var_beg;
7047
7048 if (*var_beg == '{') {
7049 var_beg++;
7050 var_end++;
7051 braces = 1;
7052 }
7053
7054 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
7055 Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
7056 err_code |= ERR_ALERT | ERR_FATAL;
7057 goto next_line; /* skip current line */
7058 }
7059
7060 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
7061 var_end++;
7062
7063 save_char = *var_end;
7064 *var_end = '\0';
7065 value = getenv(var_beg);
7066 *var_end = save_char;
7067 val_len = value ? strlen(value) : 0;
7068
7069 if (braces) {
7070 if (*var_end == '}') {
7071 var_end++;
7072 braces = 0;
7073 } else {
7074 Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
7075 err_code |= ERR_ALERT | ERR_FATAL;
7076 goto next_line; /* skip current line */
7077 }
7078 }
7079
7080 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
7081
7082 /* if not enough space in thisline */
7083 if (newlinesize > linesize) {
7084 char *newline;
7085
7086 newline = realloc(thisline, newlinesize * sizeof(*thisline));
7087 if (newline == NULL) {
7088 Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
7089 err_code |= ERR_ALERT | ERR_FATAL;
7090 goto next_line; /* slip current line */
7091 }
7092 /* recompute pointers if realloc returns a new pointer */
7093 if (newline != thisline) {
7094 int i;
7095 int diff;
7096
7097 for (i = 0; i <= arg; i++) {
7098 diff = args[i] - thisline;
7099 args[i] = newline + diff;
7100 }
7101
7102 diff = var_end - thisline;
7103 var_end = newline + diff;
7104 diff = end - thisline;
7105 end = newline + diff;
7106 diff = line - thisline;
7107 line = newline + diff;
7108 thisline = newline;
7109 }
7110 linesize = newlinesize;
7111 }
7112
7113 /* insert value inside the line */
7114 memmove(line + val_len, var_end, end - var_end + 1);
7115 memcpy(line, value, val_len);
7116 end += val_len - (var_end - line);
7117 line += val_len;
7118 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007119 else {
7120 line++;
7121 }
7122 }
William Lallemandb2f07452015-05-12 14:27:13 +02007123
William Lallemandf9873ba2015-05-05 17:37:14 +02007124 if (dquote) {
7125 Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
7126 err_code |= ERR_ALERT | ERR_FATAL;
7127 }
7128
7129 if (squote) {
7130 Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
7131 err_code |= ERR_ALERT | ERR_FATAL;
7132 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007133
7134 /* empty line */
7135 if (!**args)
7136 continue;
7137
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007138 if (*line) {
7139 /* we had to stop due to too many args.
7140 * Let's terminate the string, print the offending part then cut the
7141 * last arg.
7142 */
7143 while (*line && *line != '#' && *line != '\n' && *line != '\r')
7144 line++;
7145 *line = '\0';
7146
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01007147 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01007148 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007149 err_code |= ERR_ALERT | ERR_FATAL;
7150 args[arg] = line;
7151 }
7152
Willy Tarreau540abe42007-05-02 20:50:16 +02007153 /* zero out remaining args and ensure that at least one entry
7154 * is zeroed out.
7155 */
7156 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007157 args[arg] = line;
7158 }
7159
Willy Tarreau3842f002009-06-14 11:39:52 +02007160 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007161 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02007162 char *tmp;
7163
Willy Tarreau3842f002009-06-14 11:39:52 +02007164 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02007165 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007166 for (arg=0; *args[arg+1]; arg++)
7167 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02007168 *tmp = '\0'; // fix the next arg to \0
7169 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007170 }
Willy Tarreau3842f002009-06-14 11:39:52 +02007171 else if (!strcmp(args[0], "default")) {
7172 kwm = KWM_DEF;
7173 for (arg=0; *args[arg+1]; arg++)
7174 args[arg] = args[arg+1]; // shift args after inversion
7175 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007176
William Lallemand0f99e342011-10-12 17:50:54 +02007177 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
7178 strcmp(args[0], "log") != 0) {
7179 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02007180 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007181 }
7182
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007183 /* detect section start */
7184 list_for_each_entry(ics, &sections, list) {
7185 if (strcmp(args[0], ics->section_name) == 0) {
7186 cursection = ics->section_name;
7187 cs = ics;
7188 break;
7189 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007190 }
7191
Willy Tarreaubaaee002006-06-26 02:48:02 +02007192 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007193 if (cs)
7194 err_code |= cs->section_parser(file, linenum, args, kwm);
7195 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007196 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007197 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007198 }
Willy Tarreau058e9072009-07-20 09:30:05 +02007199
7200 if (err_code & ERR_ABORT)
7201 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007202 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01007203 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02007204 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007205 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02007206 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007207}
7208
Willy Tarreau64ab6072014-09-16 12:17:36 +02007209/* This function propagates processes from frontend <from> to backend <to> so
7210 * that it is always guaranteed that a backend pointed to by a frontend is
7211 * bound to all of its processes. After that, if the target is a "listen"
7212 * instance, the function recursively descends the target's own targets along
Willy Tarreau98d04852015-05-26 12:18:29 +02007213 * default_backend and use_backend rules. Since the bits are
Willy Tarreau64ab6072014-09-16 12:17:36 +02007214 * checked first to ensure that <to> is already bound to all processes of
7215 * <from>, there is no risk of looping and we ensure to follow the shortest
7216 * path to the destination.
7217 *
7218 * It is possible to set <to> to NULL for the first call so that the function
7219 * takes care of visiting the initial frontend in <from>.
7220 *
7221 * It is important to note that the function relies on the fact that all names
7222 * have already been resolved.
7223 */
7224void propagate_processes(struct proxy *from, struct proxy *to)
7225{
7226 struct switching_rule *rule;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007227
7228 if (to) {
7229 /* check whether we need to go down */
7230 if (from->bind_proc &&
7231 (from->bind_proc & to->bind_proc) == from->bind_proc)
7232 return;
7233
7234 if (!from->bind_proc && !to->bind_proc)
7235 return;
7236
7237 to->bind_proc = from->bind_proc ?
7238 (to->bind_proc | from->bind_proc) : 0;
7239
7240 /* now propagate down */
7241 from = to;
7242 }
7243
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01007244 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02007245 return;
7246
Willy Tarreauf6b70012014-12-18 14:00:43 +01007247 if (from->state == PR_STSTOPPED)
7248 return;
7249
Willy Tarreau64ab6072014-09-16 12:17:36 +02007250 /* default_backend */
7251 if (from->defbe.be)
7252 propagate_processes(from, from->defbe.be);
7253
7254 /* use_backend */
7255 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02007256 if (rule->dynamic)
7257 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007258 to = rule->be.backend;
7259 propagate_processes(from, to);
7260 }
Willy Tarreau64ab6072014-09-16 12:17:36 +02007261}
7262
Willy Tarreaubb925012009-07-23 13:36:36 +02007263/*
7264 * Returns the error code, 0 if OK, or any combination of :
7265 * - ERR_ABORT: must abort ASAP
7266 * - ERR_FATAL: we can continue parsing but not start the service
7267 * - ERR_WARN: a warning has been emitted
7268 * - ERR_ALERT: an alert has been emitted
7269 * Only the two first ones can stop processing, the two others are just
7270 * indicators.
7271 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007272int check_config_validity()
7273{
7274 int cfgerr = 0;
7275 struct proxy *curproxy = NULL;
7276 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02007277 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007278 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007279 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007280
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007281 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007282 /*
7283 * Now, check for the integrity of all that we have collected.
7284 */
7285
7286 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02007287 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007288
Willy Tarreau193b8c62012-11-22 00:17:38 +01007289 if (!global.tune.max_http_hdr)
7290 global.tune.max_http_hdr = MAX_HTTP_HDR;
7291
7292 if (!global.tune.cookie_len)
7293 global.tune.cookie_len = CAPTURE_LEN;
7294
7295 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
7296
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007297 /* Post initialisation of the users and groups lists. */
7298 err_code = userlist_postinit();
7299 if (err_code != ERR_NONE)
7300 goto out;
7301
Willy Tarreau55bc0f82009-03-15 14:51:53 +01007302 /* first, we will invert the proxy list order */
7303 curproxy = NULL;
7304 while (proxy) {
7305 struct proxy *next;
7306
7307 next = proxy->next;
7308 proxy->next = curproxy;
7309 curproxy = proxy;
7310 if (!next)
7311 break;
7312 proxy = next;
7313 }
7314
Willy Tarreau419ead82014-09-16 13:41:21 +02007315 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007316 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007317 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01007318 struct sticking_rule *mrule;
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007319 struct act_rule *trule;
7320 struct act_rule *hrqrule;
Dragan Dosen1322d092015-09-22 16:05:32 +02007321 struct logsrv *tmplogsrv;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007322 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01007323 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007324
Willy Tarreau050536d2012-10-04 08:47:34 +02007325 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007326 /* proxy ID not set, use automatic numbering with first
7327 * spare entry starting with next_pxid.
7328 */
7329 next_pxid = get_next_id(&used_proxy_id, next_pxid);
7330 curproxy->conf.id.key = curproxy->uuid = next_pxid;
7331 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007332 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007333 next_pxid++;
7334
Willy Tarreau55ea7572007-06-17 19:56:27 +02007335
Willy Tarreaubaaee002006-06-26 02:48:02 +02007336 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02007337 /* ensure we don't keep listeners uselessly bound */
7338 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02007339 free((void *)curproxy->table.peers.name);
7340 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007341 continue;
7342 }
7343
Willy Tarreau102df612014-05-07 23:56:38 +02007344 /* Check multi-process mode compatibility for the current proxy */
7345
7346 if (curproxy->bind_proc) {
7347 /* an explicit bind-process was specified, let's check how many
7348 * processes remain.
7349 */
David Carliere6c39412015-07-02 07:00:17 +00007350 nbproc = my_popcountl(curproxy->bind_proc);
Willy Tarreau102df612014-05-07 23:56:38 +02007351
7352 curproxy->bind_proc &= nbits(global.nbproc);
7353 if (!curproxy->bind_proc && nbproc == 1) {
7354 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);
7355 curproxy->bind_proc = 1;
7356 }
7357 else if (!curproxy->bind_proc && nbproc > 1) {
7358 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);
7359 curproxy->bind_proc = 0;
7360 }
7361 }
7362
Willy Tarreau3d209582014-05-09 17:06:11 +02007363 /* check and reduce the bind-proc of each listener */
7364 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7365 unsigned long mask;
7366
7367 if (!bind_conf->bind_proc)
7368 continue;
7369
7370 mask = nbits(global.nbproc);
7371 if (curproxy->bind_proc)
7372 mask &= curproxy->bind_proc;
7373 /* mask cannot be null here thanks to the previous checks */
7374
David Carliere6c39412015-07-02 07:00:17 +00007375 nbproc = my_popcountl(bind_conf->bind_proc);
Willy Tarreau3d209582014-05-09 17:06:11 +02007376 bind_conf->bind_proc &= mask;
7377
7378 if (!bind_conf->bind_proc && nbproc == 1) {
7379 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",
7380 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7381 bind_conf->bind_proc = mask & ~(mask - 1);
7382 }
7383 else if (!bind_conf->bind_proc && nbproc > 1) {
7384 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",
7385 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7386 bind_conf->bind_proc = 0;
7387 }
7388 }
7389
Willy Tarreauff01a212009-03-15 13:46:16 +01007390 switch (curproxy->mode) {
7391 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007392 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007393 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007394 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
7395 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007396 cfgerr++;
7397 }
7398
7399 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007400 Warning("config : servers will be ignored for %s '%s'.\n",
7401 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007402 break;
7403
7404 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007405 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007406 break;
7407
7408 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01007409 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01007410 break;
7411 }
7412
Willy Tarreauf3934b82015-08-11 11:36:45 +02007413 if ((curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->conf.listeners)) {
7414 Warning("config : %s '%s' has no 'bind' directive. Please declare it as a backend if this was intended.\n",
7415 proxy_type_str(curproxy), curproxy->id);
7416 err_code |= ERR_WARN;
7417 }
7418
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007419 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007420 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007421 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007422 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
7423 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007424 cfgerr++;
7425 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007426#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007427 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007428 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
7429 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007430 cfgerr++;
7431 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007432#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02007433 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007434 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
7435 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007436 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007437 }
7438 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02007439 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007440 /* If no LB algo is set in a backend, and we're not in
7441 * transparent mode, dispatch mode nor proxy mode, we
7442 * want to use balance roundrobin by default.
7443 */
7444 curproxy->lbprm.algo &= ~BE_LB_ALGO;
7445 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007446 }
7447 }
Willy Tarreau193cf932007-09-17 10:17:23 +02007448
Willy Tarreau1620ec32011-08-06 17:05:02 +02007449 if (curproxy->options & PR_O_DISPATCH)
7450 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
7451 else if (curproxy->options & PR_O_HTTP_PROXY)
7452 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
7453 else if (curproxy->options & PR_O_TRANSP)
7454 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01007455
Willy Tarreau1620ec32011-08-06 17:05:02 +02007456 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
7457 if (curproxy->options & PR_O_DISABLE404) {
7458 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7459 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
7460 err_code |= ERR_WARN;
7461 curproxy->options &= ~PR_O_DISABLE404;
7462 }
7463 if (curproxy->options2 & PR_O2_CHK_SNDST) {
7464 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7465 "send-state", proxy_type_str(curproxy), curproxy->id);
7466 err_code |= ERR_WARN;
7467 curproxy->options &= ~PR_O2_CHK_SNDST;
7468 }
Willy Tarreauef781042010-01-27 11:53:01 +01007469 }
7470
Simon Horman98637e52014-06-20 12:30:16 +09007471 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
7472 if (!global.external_check) {
7473 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
7474 curproxy->id, "option external-check");
7475 cfgerr++;
7476 }
7477 if (!curproxy->check_command) {
7478 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
7479 curproxy->id, "option external-check");
7480 cfgerr++;
7481 }
7482 }
7483
Simon Horman64e34162015-02-06 11:11:57 +09007484 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007485 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
7486 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Pieter Baauw8669e972015-08-17 00:45:05 +02007487 "'email-alert from', 'email-alert level' 'email-alert mailers', "
7488 "'email-alert myhostname', or 'email-alert to' "
7489 "requires each of 'email-alert from', 'email-alert mailers' and 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007490 "to be present).\n",
7491 proxy_type_str(curproxy), curproxy->id);
7492 err_code |= ERR_WARN;
7493 free_email_alert(curproxy);
7494 }
7495 if (!curproxy->email_alert.myhostname)
Cyril Bontée22bfd62015-12-04 03:07:07 +01007496 curproxy->email_alert.myhostname = strdup(hostname);
Simon Horman9dc49962015-01-30 11:22:59 +09007497 }
7498
Simon Horman98637e52014-06-20 12:30:16 +09007499 if (curproxy->check_command) {
7500 int clear = 0;
7501 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7502 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7503 "external-check command", proxy_type_str(curproxy), curproxy->id);
7504 err_code |= ERR_WARN;
7505 clear = 1;
7506 }
7507 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
Ben Cabot49795eb2015-09-16 12:07:51 +01007508 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-check path' is not set.\n",
Simon Horman98637e52014-06-20 12:30:16 +09007509 curproxy->id, "external-check command");
7510 cfgerr++;
7511 }
7512 if (clear) {
7513 free(curproxy->check_command);
7514 curproxy->check_command = NULL;
7515 }
7516 }
7517
7518 if (curproxy->check_path) {
7519 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7520 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7521 "external-check path", proxy_type_str(curproxy), curproxy->id);
7522 err_code |= ERR_WARN;
7523 free(curproxy->check_path);
7524 curproxy->check_path = NULL;
7525 }
7526 }
7527
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007528 /* if a default backend was specified, let's find it */
7529 if (curproxy->defbe.name) {
7530 struct proxy *target;
7531
Willy Tarreauafb39922015-05-26 12:04:09 +02007532 target = proxy_be_by_name(curproxy->defbe.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007533 if (!target) {
7534 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
7535 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007536 cfgerr++;
7537 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007538 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
7539 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02007540 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007541 } else if (target->mode != curproxy->mode &&
7542 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7543
7544 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) as its default backend (see 'mode').\n",
7545 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7546 curproxy->conf.file, curproxy->conf.line,
7547 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7548 target->conf.file, target->conf.line);
7549 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007550 } else {
7551 free(curproxy->defbe.name);
7552 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01007553
7554 /* Emit a warning if this proxy also has some servers */
7555 if (curproxy->srv) {
7556 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
7557 curproxy->id);
7558 err_code |= ERR_WARN;
7559 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007560 }
7561 }
7562
Willy Tarreau55ea7572007-06-17 19:56:27 +02007563 /* find the target proxy for 'use_backend' rules */
7564 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007565 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007566 struct logformat_node *node;
7567 char *pxname;
7568
7569 /* Try to parse the string as a log format expression. If the result
7570 * of the parsing is only one entry containing a simple string, then
7571 * it's a standard string corresponding to a static rule, thus the
7572 * parsing is cancelled and be.name is restored to be resolved.
7573 */
7574 pxname = rule->be.name;
7575 LIST_INIT(&rule->be.expr);
7576 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
7577 curproxy->conf.args.file, curproxy->conf.args.line);
7578 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
7579
7580 if (!LIST_ISEMPTY(&rule->be.expr)) {
7581 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
7582 rule->dynamic = 1;
7583 free(pxname);
7584 continue;
7585 }
7586 /* simple string: free the expression and fall back to static rule */
7587 free(node->arg);
7588 free(node);
7589 }
7590
7591 rule->dynamic = 0;
7592 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007593
Willy Tarreauafb39922015-05-26 12:04:09 +02007594 target = proxy_be_by_name(rule->be.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007595 if (!target) {
7596 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
7597 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007598 cfgerr++;
7599 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007600 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
7601 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007602 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007603 } else if (target->mode != curproxy->mode &&
7604 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7605
7606 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) in a 'use_backend' rule (see 'mode').\n",
7607 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7608 curproxy->conf.file, curproxy->conf.line,
7609 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7610 target->conf.file, target->conf.line);
7611 cfgerr++;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007612 } else {
7613 free((void *)rule->be.name);
7614 rule->be.backend = target;
7615 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007616 }
7617
Willy Tarreau64ab6072014-09-16 12:17:36 +02007618 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007619 list_for_each_entry(srule, &curproxy->server_rules, list) {
7620 struct server *target = findserver(curproxy, srule->srv.name);
7621
7622 if (!target) {
7623 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7624 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7625 cfgerr++;
7626 continue;
7627 }
7628 free((void *)srule->srv.name);
7629 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007630 }
7631
Emeric Brunb982a3d2010-01-04 15:45:53 +01007632 /* find the target table for 'stick' rules */
7633 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7634 struct proxy *target;
7635
Emeric Brun1d33b292010-01-04 15:47:17 +01007636 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7637 if (mrule->flags & STK_IS_STORE)
7638 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7639
Emeric Brunb982a3d2010-01-04 15:45:53 +01007640 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007641 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007642 else
7643 target = curproxy;
7644
7645 if (!target) {
7646 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7647 curproxy->id, mrule->table.name);
7648 cfgerr++;
7649 }
7650 else if (target->table.size == 0) {
7651 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7652 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7653 cfgerr++;
7654 }
Willy Tarreau12785782012-04-27 21:37:17 +02007655 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7656 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007657 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7658 cfgerr++;
7659 }
7660 else {
7661 free((void *)mrule->table.name);
7662 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007663 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007664 }
7665 }
7666
7667 /* find the target table for 'store response' rules */
7668 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7669 struct proxy *target;
7670
Emeric Brun1d33b292010-01-04 15:47:17 +01007671 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7672
Emeric Brunb982a3d2010-01-04 15:45:53 +01007673 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007674 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007675 else
7676 target = curproxy;
7677
7678 if (!target) {
7679 Alert("Proxy '%s': unable to find store table '%s'.\n",
7680 curproxy->id, mrule->table.name);
7681 cfgerr++;
7682 }
7683 else if (target->table.size == 0) {
7684 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7685 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7686 cfgerr++;
7687 }
Willy Tarreau12785782012-04-27 21:37:17 +02007688 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7689 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007690 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7691 cfgerr++;
7692 }
7693 else {
7694 free((void *)mrule->table.name);
7695 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007696 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007697 }
7698 }
7699
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007700 /* find the target table for 'tcp-request' layer 4 rules */
7701 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
7702 struct proxy *target;
7703
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007704 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007705 continue;
7706
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007707 if (trule->arg.trk_ctr.table.n)
7708 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007709 else
7710 target = curproxy;
7711
7712 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007713 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007714 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007715 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007716 cfgerr++;
7717 }
7718 else if (target->table.size == 0) {
7719 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007720 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007721 cfgerr++;
7722 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007723 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007724 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007725 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007726 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007727 cfgerr++;
7728 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007729 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007730 free(trule->arg.trk_ctr.table.n);
7731 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007732 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007733 * to pass a list of counters to track and allocate them right here using
7734 * stktable_alloc_data_type().
7735 */
7736 }
7737 }
7738
Willy Tarreaud1f96522010-08-03 19:34:32 +02007739 /* find the target table for 'tcp-request' layer 6 rules */
7740 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7741 struct proxy *target;
7742
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007743 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02007744 continue;
7745
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007746 if (trule->arg.trk_ctr.table.n)
7747 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007748 else
7749 target = curproxy;
7750
7751 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007752 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007753 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007754 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02007755 cfgerr++;
7756 }
7757 else if (target->table.size == 0) {
7758 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007759 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007760 cfgerr++;
7761 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007762 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007763 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007764 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007765 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007766 cfgerr++;
7767 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02007768 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007769 free(trule->arg.trk_ctr.table.n);
7770 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007771 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02007772 * to pass a list of counters to track and allocate them right here using
7773 * stktable_alloc_data_type().
7774 */
7775 }
7776 }
7777
Baptiste Assmanne9544932015-11-03 23:31:35 +01007778 /* parse http-request capture rules to ensure id really exists */
7779 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7780 if (hrqrule->action != ACT_CUSTOM ||
7781 hrqrule->action_ptr != http_action_req_capture_by_id)
7782 continue;
7783
7784 if (hrqrule->arg.capid.idx >= curproxy->nb_req_cap) {
7785 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-request capture rule.\n",
7786 curproxy->id, hrqrule->arg.capid.idx);
7787 cfgerr++;
7788 }
7789 }
7790
7791 /* parse http-response capture rules to ensure id really exists */
7792 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
7793 if (hrqrule->action != ACT_CUSTOM ||
7794 hrqrule->action_ptr != http_action_res_capture_by_id)
7795 continue;
7796
7797 if (hrqrule->arg.capid.idx >= curproxy->nb_rsp_cap) {
7798 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-response capture rule.\n",
7799 curproxy->id, hrqrule->arg.capid.idx);
7800 cfgerr++;
7801 }
7802 }
7803
Willy Tarreau09448f72014-06-25 18:12:15 +02007804 /* find the target table for 'http-request' layer 7 rules */
7805 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7806 struct proxy *target;
7807
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007808 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau09448f72014-06-25 18:12:15 +02007809 continue;
7810
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007811 if (hrqrule->arg.trk_ctr.table.n)
7812 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
Willy Tarreau09448f72014-06-25 18:12:15 +02007813 else
7814 target = curproxy;
7815
7816 if (!target) {
7817 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007818 curproxy->id, hrqrule->arg.trk_ctr.table.n,
Willy Tarreau09448f72014-06-25 18:12:15 +02007819 http_req_trk_idx(hrqrule->action));
7820 cfgerr++;
7821 }
7822 else if (target->table.size == 0) {
7823 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007824 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau09448f72014-06-25 18:12:15 +02007825 cfgerr++;
7826 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007827 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau09448f72014-06-25 18:12:15 +02007828 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007829 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau09448f72014-06-25 18:12:15 +02007830 http_req_trk_idx(hrqrule->action));
7831 cfgerr++;
7832 }
7833 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007834 free(hrqrule->arg.trk_ctr.table.n);
7835 hrqrule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau09448f72014-06-25 18:12:15 +02007836 /* Note: if we decide to enhance the track-sc syntax, we may be able
7837 * to pass a list of counters to track and allocate them right here using
7838 * stktable_alloc_data_type().
7839 */
7840 }
7841 }
7842
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02007843 /* move any "block" rules at the beginning of the http-request rules */
7844 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
7845 /* insert block_rules into http_req_rules at the beginning */
7846 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
7847 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
7848 curproxy->block_rules.n->p = &curproxy->http_req_rules;
7849 curproxy->http_req_rules.n = curproxy->block_rules.n;
7850 LIST_INIT(&curproxy->block_rules);
7851 }
7852
Emeric Brun32da3c42010-09-23 18:39:19 +02007853 if (curproxy->table.peers.name) {
7854 struct peers *curpeers = peers;
7855
7856 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
7857 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
7858 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01007859 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02007860 break;
7861 }
7862 }
7863
7864 if (!curpeers) {
7865 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
7866 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007867 free((void *)curproxy->table.peers.name);
7868 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007869 cfgerr++;
7870 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02007871 else if (curpeers->state == PR_STSTOPPED) {
7872 /* silently disable this peers section */
7873 curproxy->table.peers.p = NULL;
7874 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007875 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02007876 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
7877 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007878 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007879 cfgerr++;
7880 }
7881 }
7882
Simon Horman9dc49962015-01-30 11:22:59 +09007883
7884 if (curproxy->email_alert.mailers.name) {
7885 struct mailers *curmailers = mailers;
7886
7887 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
7888 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
7889 free(curproxy->email_alert.mailers.name);
7890 curproxy->email_alert.mailers.m = curmailers;
7891 curmailers->users++;
7892 break;
7893 }
7894 }
7895
7896 if (!curmailers) {
7897 Alert("Proxy '%s': unable to find mailers '%s'.\n",
7898 curproxy->id, curproxy->email_alert.mailers.name);
7899 free_email_alert(curproxy);
7900 cfgerr++;
7901 }
7902 }
7903
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007904 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01007905 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007906 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
7907 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
7908 "proxy", curproxy->id);
7909 cfgerr++;
7910 goto out_uri_auth_compat;
7911 }
7912
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007913 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007914 const char *uri_auth_compat_req[10];
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007915 struct act_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01007916 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007917
Willy Tarreau95fa4692010-02-01 13:05:50 +01007918 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
7919 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007920
7921 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007922 uri_auth_compat_req[i++] = "realm";
7923 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
7924 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007925
Willy Tarreau95fa4692010-02-01 13:05:50 +01007926 uri_auth_compat_req[i++] = "unless";
7927 uri_auth_compat_req[i++] = "{";
7928 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
7929 uri_auth_compat_req[i++] = "}";
7930 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007931
Willy Tarreauff011f22011-01-06 17:51:27 +01007932 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
7933 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007934 cfgerr++;
7935 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007936 }
7937
Willy Tarreauff011f22011-01-06 17:51:27 +01007938 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01007939
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007940 if (curproxy->uri_auth->auth_realm) {
7941 free(curproxy->uri_auth->auth_realm);
7942 curproxy->uri_auth->auth_realm = NULL;
7943 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007944
7945 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007946 }
7947out_uri_auth_compat:
7948
Dragan Dosen43885c72015-10-01 13:18:13 +02007949 /* check whether we have a log server that uses RFC5424 log format */
Dragan Dosen1322d092015-09-22 16:05:32 +02007950 list_for_each_entry(tmplogsrv, &curproxy->logsrvs, list) {
Dragan Dosen43885c72015-10-01 13:18:13 +02007951 if (tmplogsrv->format == LOG_FORMAT_RFC5424) {
7952 if (!curproxy->conf.logformat_sd_string) {
7953 /* set the default logformat_sd_string */
7954 curproxy->conf.logformat_sd_string = default_rfc5424_sd_log_format;
7955 }
Dragan Dosen1322d092015-09-22 16:05:32 +02007956 break;
Dragan Dosen1322d092015-09-22 16:05:32 +02007957 }
Dragan Dosen1322d092015-09-22 16:05:32 +02007958 }
Dragan Dosen68d2e3a2015-09-19 22:35:44 +02007959
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007960 /* compile the log format */
7961 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02007962 if (curproxy->conf.logformat_string != default_http_log_format &&
7963 curproxy->conf.logformat_string != default_tcp_log_format &&
7964 curproxy->conf.logformat_string != clf_http_log_format)
7965 free(curproxy->conf.logformat_string);
7966 curproxy->conf.logformat_string = NULL;
7967 free(curproxy->conf.lfs_file);
7968 curproxy->conf.lfs_file = NULL;
7969 curproxy->conf.lfs_line = 0;
Dragan Dosen0b85ece2015-09-25 19:17:44 +02007970
7971 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
7972 free(curproxy->conf.logformat_sd_string);
7973 curproxy->conf.logformat_sd_string = NULL;
7974 free(curproxy->conf.lfsd_file);
7975 curproxy->conf.lfsd_file = NULL;
7976 curproxy->conf.lfsd_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007977 }
7978
Willy Tarreau62a61232013-04-12 18:13:46 +02007979 if (curproxy->conf.logformat_string) {
7980 curproxy->conf.args.ctx = ARGC_LOG;
7981 curproxy->conf.args.file = curproxy->conf.lfs_file;
7982 curproxy->conf.args.line = curproxy->conf.lfs_line;
7983 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007984 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007985 curproxy->conf.args.file = NULL;
7986 curproxy->conf.args.line = 0;
7987 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007988
Dragan Dosen0b85ece2015-09-25 19:17:44 +02007989 if (curproxy->conf.logformat_sd_string) {
7990 curproxy->conf.args.ctx = ARGC_LOGSD;
7991 curproxy->conf.args.file = curproxy->conf.lfsd_file;
7992 curproxy->conf.args.line = curproxy->conf.lfsd_line;
7993 parse_logformat_string(curproxy->conf.logformat_sd_string, curproxy, &curproxy->logformat_sd, LOG_OPT_MANDATORY,
7994 SMP_VAL_FE_LOG_END, curproxy->conf.lfsd_file, curproxy->conf.lfsd_line);
7995 add_to_logformat_list(NULL, NULL, LF_SEPARATOR, &curproxy->logformat_sd);
7996 curproxy->conf.args.file = NULL;
7997 curproxy->conf.args.line = 0;
7998 }
7999
Willy Tarreau62a61232013-04-12 18:13:46 +02008000 if (curproxy->conf.uniqueid_format_string) {
8001 curproxy->conf.args.ctx = ARGC_UIF;
8002 curproxy->conf.args.file = curproxy->conf.uif_file;
8003 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01008004 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Godbachd9722032014-12-18 15:44:58 +08008005 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01008006 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02008007 curproxy->conf.args.file = NULL;
8008 curproxy->conf.args.line = 0;
8009 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008010
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01008011 /* only now we can check if some args remain unresolved.
8012 * This must be done after the users and groups resolution.
8013 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008014 cfgerr += smp_resolve_args(curproxy);
8015 if (!cfgerr)
8016 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01008017
Willy Tarreau2738a142006-07-08 17:28:09 +02008018 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008019 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02008020 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02008021 (!curproxy->timeout.connect ||
8022 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008023 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02008024 " | While not properly invalid, you will certainly encounter various problems\n"
8025 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01008026 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008027 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008028 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02008029 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02008030
Willy Tarreau1fa31262007-12-03 00:36:16 +01008031 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
8032 * We must still support older configurations, so let's find out whether those
8033 * parameters have been set or must be copied from contimeouts.
8034 */
8035 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008036 if (!curproxy->timeout.tarpit ||
8037 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008038 /* tarpit timeout not set. We search in the following order:
8039 * default.tarpit, curr.connect, default.connect.
8040 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008041 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008042 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008043 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008044 curproxy->timeout.tarpit = 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.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008047 }
8048 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008049 (!curproxy->timeout.queue ||
8050 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008051 /* queue timeout not set. We search in the following order:
8052 * default.queue, curr.connect, default.connect.
8053 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008054 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008055 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008056 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008057 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008058 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008059 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008060 }
8061 }
8062
Willy Tarreau1620ec32011-08-06 17:05:02 +02008063 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01008064 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
8065 curproxy->check_req = (char *)malloc(curproxy->check_len);
8066 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02008067 }
8068
Willy Tarreau215663d2014-06-13 18:30:23 +02008069 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
8070 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
8071 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
8072 proxy_type_str(curproxy), curproxy->id);
8073 err_code |= ERR_WARN;
8074 }
8075
Willy Tarreau193b8c62012-11-22 00:17:38 +01008076 /* ensure that cookie capture length is not too large */
8077 if (curproxy->capture_len >= global.tune.cookie_len) {
8078 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
8079 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
8080 err_code |= ERR_WARN;
8081 curproxy->capture_len = global.tune.cookie_len - 1;
8082 }
8083
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008084 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01008085 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008086 curproxy->req_cap_pool = create_pool("ptrcap",
8087 curproxy->nb_req_cap * sizeof(char *),
8088 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008089 }
8090
8091 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008092 curproxy->rsp_cap_pool = create_pool("ptrcap",
8093 curproxy->nb_rsp_cap * sizeof(char *),
8094 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008095 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008096
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02008097 switch (curproxy->load_server_state_from_file) {
8098 case PR_SRV_STATE_FILE_UNSPEC:
8099 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
8100 break;
8101 case PR_SRV_STATE_FILE_GLOBAL:
8102 if (!global.server_state_file) {
8103 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",
8104 curproxy->id);
8105 err_code |= ERR_WARN;
8106 }
8107 break;
8108 }
8109
Willy Tarreaubaaee002006-06-26 02:48:02 +02008110 /* first, we will invert the servers list order */
8111 newsrv = NULL;
8112 while (curproxy->srv) {
8113 struct server *next;
8114
8115 next = curproxy->srv->next;
8116 curproxy->srv->next = newsrv;
8117 newsrv = curproxy->srv;
8118 if (!next)
8119 break;
8120 curproxy->srv = next;
8121 }
8122
Willy Tarreau17edc812014-01-03 12:14:34 +01008123 /* Check that no server name conflicts. This causes trouble in the stats.
8124 * We only emit a warning for the first conflict affecting each server,
8125 * in order to avoid combinatory explosion if all servers have the same
8126 * name. We do that only for servers which do not have an explicit ID,
8127 * because these IDs were made also for distinguishing them and we don't
8128 * want to annoy people who correctly manage them.
8129 */
8130 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
8131 struct server *other_srv;
8132
8133 if (newsrv->puid)
8134 continue;
8135
8136 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
8137 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
8138 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
8139 newsrv->conf.file, newsrv->conf.line,
8140 proxy_type_str(curproxy), curproxy->id,
8141 newsrv->id, other_srv->conf.line);
8142 break;
8143 }
8144 }
8145 }
8146
Willy Tarreaudd701652010-05-25 23:03:02 +02008147 /* assign automatic UIDs to servers which don't have one yet */
8148 next_id = 1;
8149 newsrv = curproxy->srv;
8150 while (newsrv != NULL) {
8151 if (!newsrv->puid) {
8152 /* server ID not set, use automatic numbering with first
8153 * spare entry starting with next_svid.
8154 */
8155 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
8156 newsrv->conf.id.key = newsrv->puid = next_id;
8157 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
8158 }
8159 next_id++;
8160 newsrv = newsrv->next;
8161 }
8162
Willy Tarreau20697042007-11-15 23:26:18 +01008163 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01008164 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02008165
Willy Tarreau62c3be22012-01-20 13:12:32 +01008166 /*
8167 * If this server supports a maxconn parameter, it needs a dedicated
8168 * tasks to fill the emptied slots when a connection leaves.
8169 * Also, resolve deferred tracking dependency if needed.
8170 */
8171 newsrv = curproxy->srv;
8172 while (newsrv != NULL) {
8173 if (newsrv->minconn > newsrv->maxconn) {
8174 /* Only 'minconn' was specified, or it was higher than or equal
8175 * to 'maxconn'. Let's turn this into maxconn and clean it, as
8176 * this will avoid further useless expensive computations.
8177 */
8178 newsrv->maxconn = newsrv->minconn;
8179 } else if (newsrv->maxconn && !newsrv->minconn) {
8180 /* minconn was not specified, so we set it to maxconn */
8181 newsrv->minconn = newsrv->maxconn;
8182 }
8183
Emeric Brun01f8e2f2012-05-18 16:02:00 +02008184#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02008185 if (newsrv->use_ssl || newsrv->check.use_ssl)
8186 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02008187#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02008188
Willy Tarreau2f075e92013-12-03 11:11:34 +01008189 /* set the check type on the server */
8190 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
8191
Willy Tarreau62c3be22012-01-20 13:12:32 +01008192 if (newsrv->trackit) {
8193 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02008194 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008195 char *pname, *sname;
8196
8197 pname = newsrv->trackit;
8198 sname = strrchr(pname, '/');
8199
8200 if (sname)
8201 *sname++ = '\0';
8202 else {
8203 sname = pname;
8204 pname = NULL;
8205 }
8206
8207 if (pname) {
Willy Tarreau9e0bb102015-05-26 11:24:42 +02008208 px = proxy_be_by_name(pname);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008209 if (!px) {
8210 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
8211 proxy_type_str(curproxy), curproxy->id,
8212 newsrv->id, pname);
8213 cfgerr++;
8214 goto next_srv;
8215 }
8216 } else
8217 px = curproxy;
8218
8219 srv = findserver(px, sname);
8220 if (!srv) {
8221 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
8222 proxy_type_str(curproxy), curproxy->id,
8223 newsrv->id, sname);
8224 cfgerr++;
8225 goto next_srv;
8226 }
8227
Willy Tarreau32091232014-05-16 13:52:00 +02008228 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
8229 !(srv->agent.state & CHK_ST_CONFIGURED) &&
8230 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01008231 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02008232 "tracking as it does not have any check nor agent enabled.\n",
8233 proxy_type_str(curproxy), curproxy->id,
8234 newsrv->id, px->id, srv->id);
8235 cfgerr++;
8236 goto next_srv;
8237 }
8238
8239 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
8240
8241 if (loop) {
8242 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
8243 "belongs to a tracking chain looping back to %s/%s.\n",
8244 proxy_type_str(curproxy), curproxy->id,
8245 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008246 cfgerr++;
8247 goto next_srv;
8248 }
8249
8250 if (curproxy != px &&
8251 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
8252 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
8253 "tracking: disable-on-404 option inconsistency.\n",
8254 proxy_type_str(curproxy), curproxy->id,
8255 newsrv->id, px->id, srv->id);
8256 cfgerr++;
8257 goto next_srv;
8258 }
8259
8260 /* if the other server is forced disabled, we have to do the same here */
Willy Tarreau20125212014-05-13 19:44:56 +02008261 if (srv->admin & SRV_ADMF_MAINT) {
Willy Tarreaua0066dd2014-05-16 11:25:16 +02008262 newsrv->admin |= SRV_ADMF_IMAINT;
Willy Tarreau892337c2014-05-13 23:41:20 +02008263 newsrv->state = SRV_ST_STOPPED;
Simon Horman125d0992013-02-24 17:23:38 +09008264 newsrv->check.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008265 }
8266
8267 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01008268 newsrv->tracknext = srv->trackers;
8269 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008270
8271 free(newsrv->trackit);
8272 newsrv->trackit = NULL;
8273 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008274
8275 /*
8276 * resolve server's resolvers name and update the resolvers pointer
8277 * accordingly
8278 */
8279 if (newsrv->resolvers_id) {
8280 struct dns_resolvers *curr_resolvers;
8281 int found;
8282
8283 found = 0;
8284 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
8285 if (!strcmp(curr_resolvers->id, newsrv->resolvers_id)) {
8286 found = 1;
8287 break;
8288 }
8289 }
8290
8291 if (!found) {
8292 Alert("config : %s '%s', server '%s': unable to find required resolvers '%s'\n",
8293 proxy_type_str(curproxy), curproxy->id,
8294 newsrv->id, newsrv->resolvers_id);
8295 cfgerr++;
8296 } else {
8297 free(newsrv->resolvers_id);
8298 newsrv->resolvers_id = NULL;
8299 if (newsrv->resolution)
8300 newsrv->resolution->resolvers = curr_resolvers;
8301 }
8302 }
8303 else {
8304 /* if no resolvers section associated to this server
8305 * we can clean up the associated resolution structure
8306 */
8307 if (newsrv->resolution) {
8308 free(newsrv->resolution->hostname_dn);
8309 newsrv->resolution->hostname_dn = NULL;
8310 free(newsrv->resolution);
8311 newsrv->resolution = NULL;
8312 }
8313 }
8314
Willy Tarreau62c3be22012-01-20 13:12:32 +01008315 next_srv:
8316 newsrv = newsrv->next;
8317 }
8318
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008319 /* We have to initialize the server lookup mechanism depending
8320 * on what LB algorithm was choosen.
8321 */
8322
8323 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
8324 switch (curproxy->lbprm.algo & BE_LB_KIND) {
8325 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02008326 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
8327 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8328 init_server_map(curproxy);
8329 } else {
8330 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
8331 fwrr_init_server_groups(curproxy);
8332 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008333 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008334
Willy Tarreau3ebb1162012-02-13 16:57:44 +01008335 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01008336 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
8337 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
8338 fwlc_init_server_tree(curproxy);
8339 } else {
8340 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
8341 fas_init_server_tree(curproxy);
8342 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008343 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008344
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008345 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008346 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
8347 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
8348 chash_init_server_tree(curproxy);
8349 } else {
8350 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8351 init_server_map(curproxy);
8352 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008353 break;
8354 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02008355
8356 if (curproxy->options & PR_O_LOGASAP)
8357 curproxy->to_log &= ~LW_BYTES;
8358
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008359 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008360 (curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->logsrvs) &&
8361 (!LIST_ISEMPTY(&curproxy->logformat) || !LIST_ISEMPTY(&curproxy->logformat_sd))) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008362 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
8363 proxy_type_str(curproxy), curproxy->id);
8364 err_code |= ERR_WARN;
8365 }
8366
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008367 if (curproxy->mode != PR_MODE_HTTP) {
8368 int optnum;
8369
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008370 if (curproxy->uri_auth) {
8371 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
8372 proxy_type_str(curproxy), curproxy->id);
8373 err_code |= ERR_WARN;
8374 curproxy->uri_auth = NULL;
8375 }
8376
Willy Tarreau87cf5142011-08-19 22:57:24 +02008377 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008378 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8379 "forwardfor", proxy_type_str(curproxy), curproxy->id);
8380 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02008381 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008382 }
8383
8384 if (curproxy->options & PR_O_ORGTO) {
8385 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8386 "originalto", proxy_type_str(curproxy), curproxy->id);
8387 err_code |= ERR_WARN;
8388 curproxy->options &= ~PR_O_ORGTO;
8389 }
8390
8391 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
8392 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
8393 (curproxy->cap & cfg_opts[optnum].cap) &&
8394 (curproxy->options & cfg_opts[optnum].val)) {
8395 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8396 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
8397 err_code |= ERR_WARN;
8398 curproxy->options &= ~cfg_opts[optnum].val;
8399 }
8400 }
8401
8402 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
8403 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
8404 (curproxy->cap & cfg_opts2[optnum].cap) &&
8405 (curproxy->options2 & cfg_opts2[optnum].val)) {
8406 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8407 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
8408 err_code |= ERR_WARN;
8409 curproxy->options2 &= ~cfg_opts2[optnum].val;
8410 }
8411 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008412
Willy Tarreau29fbe512015-08-20 19:35:14 +02008413#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008414 if (curproxy->conn_src.bind_hdr_occ) {
8415 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008416 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01008417 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008418 err_code |= ERR_WARN;
8419 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008420#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008421 }
8422
Willy Tarreaubaaee002006-06-26 02:48:02 +02008423 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01008424 * ensure that we're not cross-dressing a TCP server into HTTP.
8425 */
8426 newsrv = curproxy->srv;
8427 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01008428 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008429 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
8430 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008431 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01008432 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008433
Willy Tarreau0cec3312011-10-31 13:49:26 +01008434 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
8435 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
8436 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8437 err_code |= ERR_WARN;
8438 }
8439
Willy Tarreauc93cd162014-05-13 15:54:22 +02008440 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02008441 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
8442 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8443 err_code |= ERR_WARN;
8444 }
8445
Willy Tarreau29fbe512015-08-20 19:35:14 +02008446#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008447 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
8448 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008449 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 +01008450 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008451 err_code |= ERR_WARN;
8452 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008453#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01008454 newsrv = newsrv->next;
8455 }
8456
Willy Tarreaue42bd962014-09-16 16:21:19 +02008457 /* check if we have a frontend with "tcp-request content" looking at L7
8458 * with no inspect-delay
8459 */
8460 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
8461 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008462 if (trule->action == ACT_TCP_CAPTURE &&
Thierry FOURNIERd0d65ae2015-08-04 08:21:12 +02008463 !(trule->arg.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008464 break;
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008465 if ((trule->action >= ACT_ACTION_TRK_SC0 && trule->action <= ACT_ACTION_TRK_SCMAX) &&
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008466 !(trule->arg.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008467 break;
8468 }
8469
8470 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
8471 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
8472 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
8473 " This means that these rules will randomly find their contents. This can be fixed by"
8474 " setting the tcp-request inspect-delay.\n",
8475 proxy_type_str(curproxy), curproxy->id);
8476 err_code |= ERR_WARN;
8477 }
8478 }
8479
Willy Tarreauc1a21672009-08-16 22:37:44 +02008480 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02008481 if (!curproxy->accept)
8482 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02008483
Willy Tarreauc1a21672009-08-16 22:37:44 +02008484 if (curproxy->tcp_req.inspect_delay ||
8485 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02008486 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008487
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008488 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008489 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008490 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008491 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008492
8493 /* both TCP and HTTP must check switching rules */
8494 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
8495 }
8496
8497 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02008498 if (curproxy->tcp_req.inspect_delay ||
8499 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
8500 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
8501
Emeric Brun97679e72010-09-23 17:56:44 +02008502 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
8503 curproxy->be_rsp_ana |= AN_RES_INSPECT;
8504
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008505 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008506 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008507 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008508 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008509
8510 /* If the backend does requires RDP cookie persistence, we have to
8511 * enable the corresponding analyser.
8512 */
8513 if (curproxy->options2 & PR_O2_RDPC_PRST)
8514 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
8515 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008516 }
8517
8518 /***********************************************************/
8519 /* At this point, target names have already been resolved. */
8520 /***********************************************************/
8521
8522 /* Check multi-process mode compatibility */
8523
8524 if (global.nbproc > 1 && global.stats_fe) {
8525 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8526 unsigned long mask;
8527
8528 mask = nbits(global.nbproc);
8529 if (global.stats_fe->bind_proc)
8530 mask &= global.stats_fe->bind_proc;
8531
8532 if (bind_conf->bind_proc)
8533 mask &= bind_conf->bind_proc;
8534
8535 /* stop here if more than one process is used */
David Carliere6c39412015-07-02 07:00:17 +00008536 if (my_popcountl(mask) > 1)
Willy Tarreau419ead82014-09-16 13:41:21 +02008537 break;
8538 }
8539 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
8540 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");
8541 }
8542 }
8543
8544 /* Make each frontend inherit bind-process from its listeners when not specified. */
8545 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8546 if (curproxy->bind_proc)
8547 continue;
8548
8549 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8550 unsigned long mask;
8551
Willy Tarreaue428b082015-05-04 21:57:58 +02008552 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008553 curproxy->bind_proc |= mask;
8554 }
8555
8556 if (!curproxy->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008557 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008558 }
8559
8560 if (global.stats_fe) {
8561 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8562 unsigned long mask;
8563
Willy Tarreaue428b082015-05-04 21:57:58 +02008564 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008565 global.stats_fe->bind_proc |= mask;
8566 }
8567 if (!global.stats_fe->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008568 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008569 }
8570
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02008571 /* propagate bindings from frontends to backends. Don't do it if there
8572 * are any fatal errors as we must not call it with unresolved proxies.
8573 */
8574 if (!cfgerr) {
8575 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8576 if (curproxy->cap & PR_CAP_FE)
8577 propagate_processes(curproxy, NULL);
8578 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008579 }
8580
8581 /* Bind each unbound backend to all processes when not specified. */
8582 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8583 if (curproxy->bind_proc)
8584 continue;
Willy Tarreaue428b082015-05-04 21:57:58 +02008585 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008586 }
8587
8588 /*******************************************************/
8589 /* At this step, all proxies have a non-null bind_proc */
8590 /*******************************************************/
8591
8592 /* perform the final checks before creating tasks */
8593
8594 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8595 struct listener *listener;
8596 unsigned int next_id;
8597 int nbproc;
8598
David Carliere6c39412015-07-02 07:00:17 +00008599 nbproc = my_popcountl(curproxy->bind_proc & nbits(global.nbproc));
Willy Tarreauc1a21672009-08-16 22:37:44 +02008600
Emeric Brunc52962f2012-11-15 18:28:02 +01008601#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008602 /* Configure SSL for each bind line.
8603 * Note: if configuration fails at some point, the ->ctx member
8604 * remains NULL so that listeners can later detach.
8605 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008606 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008607 int alloc_ctx;
8608
Emeric Brunc52962f2012-11-15 18:28:02 +01008609 if (!bind_conf->is_ssl) {
8610 if (bind_conf->default_ctx) {
8611 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
8612 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
8613 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008614 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01008615 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008616 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02008617 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008618 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008619 cfgerr++;
8620 continue;
8621 }
8622
Emeric Brun8dc60392014-05-09 13:52:00 +02008623 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008624 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02008625 if (alloc_ctx == SHCTX_E_INIT_LOCK)
8626 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");
8627 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008628 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02008629 cfgerr++;
8630 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008631 }
8632
Emeric Brunfc0421f2012-09-07 17:30:07 +02008633 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008634 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008635
8636 /* initialize CA variables if the certificates generation is enabled */
8637 cfgerr += ssl_sock_load_ca(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008638 }
Emeric Brunc52962f2012-11-15 18:28:02 +01008639#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008640
Willy Tarreaue6b98942007-10-29 01:09:36 +01008641 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008642 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008643 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008644 if (!listener->luid) {
8645 /* listener ID not set, use automatic numbering with first
8646 * spare entry starting with next_luid.
8647 */
8648 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
8649 listener->conf.id.key = listener->luid = next_id;
8650 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008651 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01008652 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008653
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008654 /* enable separate counters */
8655 if (curproxy->options2 & PR_O2_SOCKSTAT) {
8656 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01008657 if (!listener->name)
8658 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008659 }
Willy Tarreau81796be2012-09-22 19:11:47 +02008660
Willy Tarreaue6b98942007-10-29 01:09:36 +01008661 if (curproxy->options & PR_O_TCP_NOLING)
8662 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02008663 if (!listener->maxconn)
8664 listener->maxconn = curproxy->maxconn;
8665 if (!listener->backlog)
8666 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01008667 if (!listener->maxaccept)
8668 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
8669
8670 /* we want to have an optimal behaviour on single process mode to
8671 * maximize the work at once, but in multi-process we want to keep
8672 * some fairness between processes, so we target half of the max
8673 * number of events to be balanced over all the processes the proxy
8674 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
8675 * used to disable the limit.
8676 */
8677 if (listener->maxaccept > 0) {
8678 if (nbproc > 1)
8679 listener->maxaccept = (listener->maxaccept + 1) / 2;
8680 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
8681 }
8682
Willy Tarreau9903f0e2015-04-04 18:50:31 +02008683 listener->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02008684 listener->handler = process_stream;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008685 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01008686 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01008687
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008688 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
8689 listener->options |= LI_O_TCP_RULES;
8690
Willy Tarreaude3041d2010-05-31 10:56:17 +02008691 if (curproxy->mon_mask.s_addr)
8692 listener->options |= LI_O_CHK_MONNET;
8693
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008694 /* smart accept mode is automatic in HTTP mode */
8695 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008696 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008697 !(curproxy->no_options2 & PR_O2_SMARTACC)))
8698 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01008699 }
8700
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008701 /* Release unused SSL configs */
8702 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8703 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008704 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008705#ifdef USE_OPENSSL
Christopher Faulet31af49d2015-06-09 17:29:50 +02008706 ssl_sock_free_ca(bind_conf);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008707 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008708 free(bind_conf->ca_file);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008709 free(bind_conf->ca_sign_file);
8710 free(bind_conf->ca_sign_pass);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008711 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02008712 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008713 free(bind_conf->crl_file);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008714 if(bind_conf->keys_ref) {
8715 free(bind_conf->keys_ref->filename);
8716 free(bind_conf->keys_ref->tlskeys);
8717 free(bind_conf->keys_ref);
8718 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008719#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008720 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008721
Willy Tarreau102df612014-05-07 23:56:38 +02008722 if (nbproc > 1) {
8723 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02008724 int count, maxproc = 0;
8725
8726 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
David Carliere6c39412015-07-02 07:00:17 +00008727 count = my_popcountl(bind_conf->bind_proc);
Willy Tarreaueb791e02014-09-16 15:11:04 +02008728 if (count > maxproc)
8729 maxproc = count;
8730 }
8731 /* backends have 0, frontends have 1 or more */
8732 if (maxproc != 1)
8733 Warning("Proxy '%s': in multi-process mode, stats will be"
8734 " limited to process assigned to the current request.\n",
8735 curproxy->id);
8736
Willy Tarreau102df612014-05-07 23:56:38 +02008737 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
8738 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
8739 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008740 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008741 }
Willy Tarreau102df612014-05-07 23:56:38 +02008742 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
8743 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
8744 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008745 }
8746 }
Willy Tarreau918ff602011-07-25 16:33:49 +02008747
8748 /* create the task associated with the proxy */
8749 curproxy->task = task_new();
8750 if (curproxy->task) {
8751 curproxy->task->context = curproxy;
8752 curproxy->task->process = manage_proxy;
8753 /* no need to queue, it will be done automatically if some
8754 * listener gets limited.
8755 */
8756 curproxy->task->expire = TICK_ETERNITY;
8757 } else {
8758 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
8759 curproxy->id);
8760 cfgerr++;
8761 }
Willy Tarreaub369a042014-09-16 13:21:03 +02008762 }
8763
Willy Tarreaufbb78422011-06-05 15:38:35 +02008764 /* automatically compute fullconn if not set. We must not do it in the
8765 * loop above because cross-references are not yet fully resolved.
8766 */
8767 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8768 /* If <fullconn> is not set, let's set it to 10% of the sum of
8769 * the possible incoming frontend's maxconns.
8770 */
8771 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
8772 struct proxy *fe;
8773 int total = 0;
8774
8775 /* sum up the number of maxconns of frontends which
8776 * reference this backend at least once or which are
8777 * the same one ('listen').
8778 */
8779 for (fe = proxy; fe; fe = fe->next) {
8780 struct switching_rule *rule;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008781 int found = 0;
8782
8783 if (!(fe->cap & PR_CAP_FE))
8784 continue;
8785
8786 if (fe == curproxy) /* we're on a "listen" instance */
8787 found = 1;
8788
8789 if (fe->defbe.be == curproxy) /* "default_backend" */
8790 found = 1;
8791
8792 /* check if a "use_backend" rule matches */
8793 if (!found) {
8794 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01008795 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02008796 found = 1;
8797 break;
8798 }
8799 }
8800 }
8801
Willy Tarreaufbb78422011-06-05 15:38:35 +02008802 /* now we've checked all possible ways to reference a backend
8803 * from a frontend.
8804 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02008805 if (!found)
8806 continue;
8807 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008808 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02008809 /* we have the sum of the maxconns in <total>. We only
8810 * keep 10% of that sum to set the default fullconn, with
8811 * a hard minimum of 1 (to avoid a divide by zero).
8812 */
8813 curproxy->fullconn = (total + 9) / 10;
8814 if (!curproxy->fullconn)
8815 curproxy->fullconn = 1;
8816 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01008817 }
8818
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008819 /*
8820 * Recount currently required checks.
8821 */
8822
8823 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
8824 int optnum;
8825
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008826 for (optnum = 0; cfg_opts[optnum].name; optnum++)
8827 if (curproxy->options & cfg_opts[optnum].val)
8828 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008829
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008830 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
8831 if (curproxy->options2 & cfg_opts2[optnum].val)
8832 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008833 }
8834
Willy Tarreau0fca4832015-05-01 19:12:05 +02008835 /* compute the required process bindings for the peers */
8836 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
8837 if (curproxy->table.peers.p)
8838 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
8839
Willy Tarreau122541c2011-09-07 21:24:49 +02008840 if (peers) {
8841 struct peers *curpeers = peers, **last;
8842 struct peer *p, *pb;
8843
Willy Tarreau1e273012015-05-01 19:15:17 +02008844 /* Remove all peers sections which don't have a valid listener,
8845 * which are not used by any table, or which are bound to more
8846 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02008847 */
8848 last = &peers;
8849 while (*last) {
8850 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008851
8852 if (curpeers->state == PR_STSTOPPED) {
8853 /* the "disabled" keyword was present */
8854 if (curpeers->peers_fe)
8855 stop_proxy(curpeers->peers_fe);
8856 curpeers->peers_fe = NULL;
8857 }
8858 else if (!curpeers->peers_fe) {
8859 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
8860 curpeers->id, localpeer);
8861 }
David Carliere6c39412015-07-02 07:00:17 +00008862 else if (my_popcountl(curpeers->peers_fe->bind_proc) != 1) {
Willy Tarreau1e273012015-05-01 19:15:17 +02008863 /* either it's totally stopped or too much used */
8864 if (curpeers->peers_fe->bind_proc) {
8865 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreau64c57222015-05-04 21:48:51 +02008866 "running in different processes (%d different ones). "
8867 "Check global.nbproc and all tables' bind-process "
David Carliere6c39412015-07-02 07:00:17 +00008868 "settings.\n", curpeers->id, my_popcountl(curpeers->peers_fe->bind_proc));
Willy Tarreau1e273012015-05-01 19:15:17 +02008869 cfgerr++;
8870 }
8871 stop_proxy(curpeers->peers_fe);
8872 curpeers->peers_fe = NULL;
8873 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008874 else {
Emeric Brunb3971ab2015-05-12 18:49:09 +02008875 peers_init_sync(curpeers);
Willy Tarreau122541c2011-09-07 21:24:49 +02008876 last = &curpeers->next;
8877 continue;
8878 }
8879
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008880 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02008881 p = curpeers->remote;
8882 while (p) {
8883 pb = p->next;
8884 free(p->id);
8885 free(p);
8886 p = pb;
8887 }
8888
8889 /* Destroy and unlink this curpeers section.
8890 * Note: curpeers is backed up into *last.
8891 */
8892 free(curpeers->id);
8893 curpeers = curpeers->next;
8894 free(*last);
8895 *last = curpeers;
8896 }
8897 }
8898
Willy Tarreau6866f3f2015-05-01 19:09:08 +02008899 /* initialize stick-tables on backend capable proxies. This must not
8900 * be done earlier because the data size may be discovered while parsing
8901 * other proxies.
8902 */
8903 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8904 if (curproxy->state == PR_STSTOPPED)
8905 continue;
8906
8907 if (!stktable_init(&curproxy->table)) {
8908 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
8909 cfgerr++;
8910 }
8911 }
8912
Simon Horman0d16a402015-01-30 11:22:58 +09008913 if (mailers) {
8914 struct mailers *curmailers = mailers, **last;
8915 struct mailer *m, *mb;
8916
8917 /* Remove all mailers sections which don't have a valid listener.
8918 * This can happen when a mailers section is never referenced.
8919 */
8920 last = &mailers;
8921 while (*last) {
8922 curmailers = *last;
8923 if (curmailers->users) {
8924 last = &curmailers->next;
8925 continue;
8926 }
8927
8928 Warning("Removing incomplete section 'mailers %s'.\n",
8929 curmailers->id);
8930
8931 m = curmailers->mailer_list;
8932 while (m) {
8933 mb = m->next;
8934 free(m->id);
8935 free(m);
8936 m = mb;
8937 }
8938
8939 /* Destroy and unlink this curmailers section.
8940 * Note: curmailers is backed up into *last.
8941 */
8942 free(curmailers->id);
8943 curmailers = curmailers->next;
8944 free(*last);
8945 *last = curmailers;
8946 }
8947 }
8948
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02008949 /* Update server_state_file_name to backend name if backend is supposed to use
8950 * a server-state file locally defined and none has been provided */
8951 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8952 if (curproxy->load_server_state_from_file == PR_SRV_STATE_FILE_LOCAL &&
8953 curproxy->server_state_file_name == NULL)
8954 curproxy->server_state_file_name = strdup(curproxy->id);
8955 }
8956
Willy Tarreau34eb6712011-10-24 18:15:04 +02008957 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02008958 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02008959 MEM_F_SHARED);
8960
Willy Tarreaubb925012009-07-23 13:36:36 +02008961 if (cfgerr > 0)
8962 err_code |= ERR_ALERT | ERR_FATAL;
8963 out:
8964 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02008965}
8966
Willy Tarreau5b2c3362008-07-09 19:39:06 +02008967/*
8968 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
8969 * parsing sessions.
8970 */
8971void cfg_register_keywords(struct cfg_kw_list *kwl)
8972{
8973 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
8974}
Willy Tarreaubaaee002006-06-26 02:48:02 +02008975
Willy Tarreau5b2c3362008-07-09 19:39:06 +02008976/*
8977 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
8978 */
8979void cfg_unregister_keywords(struct cfg_kw_list *kwl)
8980{
8981 LIST_DEL(&kwl->list);
8982 LIST_INIT(&kwl->list);
8983}
Willy Tarreaubaaee002006-06-26 02:48:02 +02008984
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01008985/* this function register new section in the haproxy configuration file.
8986 * <section_name> is the name of this new section and <section_parser>
8987 * is the called parser. If two section declaration have the same name,
8988 * only the first declared is used.
8989 */
8990int cfg_register_section(char *section_name,
8991 int (*section_parser)(const char *, int, char **, int))
8992{
8993 struct cfg_section *cs;
8994
8995 cs = calloc(1, sizeof(*cs));
8996 if (!cs) {
8997 Alert("register section '%s': out of memory.\n", section_name);
8998 return 0;
8999 }
9000
9001 cs->section_name = section_name;
9002 cs->section_parser = section_parser;
9003
9004 LIST_ADDQ(&sections, &cs->list);
9005
9006 return 1;
9007}
9008
Willy Tarreaubaaee002006-06-26 02:48:02 +02009009/*
David Carlier845efb52015-09-25 11:49:18 +01009010 * free all config section entries
9011 */
9012void cfg_unregister_sections(void)
9013{
9014 struct cfg_section *cs, *ics;
9015
9016 list_for_each_entry_safe(cs, ics, &sections, list) {
9017 LIST_DEL(&cs->list);
9018 free(cs);
9019 }
9020}
9021
9022/*
Willy Tarreaubaaee002006-06-26 02:48:02 +02009023 * Local variables:
9024 * c-indent-level: 8
9025 * c-basic-offset: 8
9026 * End:
9027 */