blob: 97f42430972c7fe891364591ae2463629d3b956d [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreauff011f22011-01-06 17:51:27 +01004 * Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
Cyril Bonté1a0191d2014-08-29 20:20:02 +020013#ifdef CONFIG_HAP_CRYPT
14/* This is to have crypt() defined on Linux */
15#define _GNU_SOURCE
16
17#ifdef NEED_CRYPT_H
18/* some platforms such as Solaris need this */
19#include <crypt.h>
20#endif
21#endif /* CONFIG_HAP_CRYPT */
22
Willy Tarreaubaaee002006-06-26 02:48:02 +020023#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <netdb.h>
27#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020028#include <pwd.h>
29#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020030#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020031#include <sys/types.h>
32#include <sys/stat.h>
33#include <fcntl.h>
34#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
Willy Tarreau2dd0d472006-06-29 17:53:05 +020036#include <common/cfgparse.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020037#include <common/chunk.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020038#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020039#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020040#include <common/memory.h>
41#include <common/standard.h>
42#include <common/time.h>
43#include <common/uri_auth.h>
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +010044#include <common/namespace.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020045
46#include <types/capture.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020047#include <types/compression.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020048#include <types/global.h>
Willy Tarreau3fdb3662012-11-12 00:42:33 +010049#include <types/obj_type.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020050#include <types/peers.h>
Simon Horman0d16a402015-01-30 11:22:58 +090051#include <types/mailers.h>
Baptiste Assmann325137d2015-04-13 23:40:55 +020052#include <types/dns.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020053
Willy Tarreaueb0c6142007-05-07 00:53:22 +020054#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010055#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020056#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020057#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020058#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020059#include <proto/compression.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020060#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020061#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020062#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020063#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010064#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020065#include <proto/lb_fwlc.h>
66#include <proto/lb_fwrr.h>
67#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020068#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020069#include <proto/log.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020070#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010071#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020072#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010073#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010074#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020075#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020076#include <proto/sample.h>
Willy Tarreau9903f0e2015-04-04 18:50:31 +020077#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020078#include <proto/server.h>
Willy Tarreau87b09662015-04-03 00:22:06 +020079#include <proto/stream.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020080#include <proto/raw_sock.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020081#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010082#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020083
Emeric Brunfc0421f2012-09-07 17:30:07 +020084#ifdef USE_OPENSSL
85#include <types/ssl_sock.h>
86#include <proto/ssl_sock.h>
87#include <proto/shctx.h>
88#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020089
Willy Tarreauf3c69202006-07-09 16:42:34 +020090/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
91 * ssl-hello-chk option to ensure that the remote server speaks SSL.
92 *
93 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
94 */
95const char sslv3_client_hello_pkt[] = {
96 "\x16" /* ContentType : 0x16 = Hanshake */
97 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
98 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
99 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
100 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
101 "\x03\x00" /* Hello Version : 0x0300 = v3 */
102 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
103 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
104 "\x00" /* Session ID length : empty (no session ID) */
105 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
106 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
107 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
108 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
109 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
110 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
111 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
112 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
113 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
114 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
115 "\x00\x38" "\x00\x39" "\x00\x3A"
116 "\x01" /* Compression Length : 0x01 = 1 byte for types */
117 "\x00" /* Compression Type : 0x00 = NULL compression */
118};
119
Willy Tarreau3842f002009-06-14 11:39:52 +0200120/* various keyword modifiers */
121enum kw_mod {
122 KWM_STD = 0, /* normal */
123 KWM_NO, /* "no" prefixed before the keyword */
124 KWM_DEF, /* "default" prefixed before the keyword */
125};
126
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +0100127/* permit to store configuration section */
128struct cfg_section {
129 struct list list;
130 char *section_name;
131 int (*section_parser)(const char *, int, char **, int);
132};
133
134/* Used to chain configuration sections definitions. This list
135 * stores struct cfg_section
136 */
137struct list sections = LIST_HEAD_INIT(sections);
138
Willy Tarreau13943ab2006-12-31 00:24:10 +0100139/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100140struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100141 const char *name;
142 unsigned int val;
143 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100144 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100145 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100146};
147
148/* proxy->options */
149static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100150{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100151 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
152 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
153 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
154 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
155 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
156 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100157 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau9fbe18e2015-05-01 22:42:08 +0200158 { "http-buffer-request", PR_O_WREQ_BODY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau0f228a02015-05-01 15:37:53 +0200159 { "http-ignore-probes", PR_O_IGNORE_PRB, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreau9420b122013-12-15 18:58:25 +0100160 { "prefer-last-server", PR_O_PREF_LAST, PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100161 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
162 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
163 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100164 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100165#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100166 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100167#else
168 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100169#endif
170
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100171 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100172};
173
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100174/* proxy->options2 */
175static const struct cfg_opt cfg_opts2[] =
176{
177#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100178 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
179 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
180 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100181#else
182 { "splice-request", 0, 0, 0, 0 },
183 { "splice-response", 0, 0, 0, 0 },
184 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100185#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100186 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
187 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
188 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
189 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
190 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
191 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
192 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
193 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
194 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400195 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100196 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200197 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200198 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100199 { NULL, 0, 0, 0 }
200};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200201
Willy Tarreau6daf3432008-01-22 16:44:08 +0100202static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200203static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
204int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100205int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200206
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200207/* List head of all known configuration keywords */
208static struct cfg_kw_list cfg_keywords = {
209 .list = LIST_HEAD_INIT(cfg_keywords.list)
210};
211
Willy Tarreaubaaee002006-06-26 02:48:02 +0200212/*
213 * converts <str> to a list of listeners which are dynamically allocated.
214 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
215 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
216 * - <port> is a numerical port from 1 to 65535 ;
217 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
218 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200219 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
220 * not NULL, it must be a valid pointer to either NULL or a freeable area that
221 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200222 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200223int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf, const char *file, int line, char **err)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200224{
225 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100226 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200227 int port, end;
228
229 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200230
Willy Tarreaubaaee002006-06-26 02:48:02 +0200231 while (next && *next) {
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100232 struct sockaddr_storage ss, *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100233 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200234
235 str = next;
236 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100237 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200238 *next++ = 0;
239 }
240
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100241 ss2 = str2sa_range(str, &port, &end, err,
Willy Tarreau72b8c1f2015-09-08 15:50:19 +0200242 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix,
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +0200243 NULL, 1);
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100244 if (!ss2)
245 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200246
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100247 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100248 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200249 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100250 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200251 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200252
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100253 if (!port || !end) {
254 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
255 goto fail;
256 }
257
Emeric Bruned760922010-10-22 17:59:25 +0200258 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200259 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200260 goto fail;
261 }
262
263 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200264 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200265 goto fail;
266 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200267 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100268 else if (ss2->ss_family == AF_UNSPEC) {
269 socklen_t addr_len;
270
271 /* We want to attach to an already bound fd whose number
272 * is in the addr part of ss2 when cast to sockaddr_in.
273 * Note that by definition there is a single listener.
274 * We still have to determine the address family to
275 * register the correct protocol.
276 */
277 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
278 addr_len = sizeof(*ss2);
279 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
280 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
281 goto fail;
282 }
283
284 port = end = get_host_port(ss2);
285 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200286
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100287 /* OK the address looks correct */
288 ss = *ss2;
289
Willy Tarreaubaaee002006-06-26 02:48:02 +0200290 for (; port <= end; port++) {
291 l = (struct listener *)calloc(1, sizeof(struct listener));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100292 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200293 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
294 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
295 l->frontend = curproxy;
296 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200297
Willy Tarreau40aa0702013-03-10 23:51:38 +0100298 l->fd = fd;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200299 l->addr = ss;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200300 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100301 l->state = LI_INIT;
302
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100303 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200304 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100305 tcpv4_add_listener(l);
306 }
Emeric Bruned760922010-10-22 17:59:25 +0200307 else if (ss.ss_family == AF_INET6) {
308 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
309 tcpv6_add_listener(l);
310 }
311 else {
Emeric Bruned760922010-10-22 17:59:25 +0200312 uxst_add_listener(l);
313 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200314
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200315 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100316 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200317 } /* end for(port) */
318 } /* end while(next) */
319 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200320 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200321 fail:
322 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200323 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200324}
325
William Lallemand6e62fb62015-04-28 16:55:23 +0200326/*
327 * Report a fatal Alert when there is too much arguments
328 * The index is the current keyword in args
329 * Return 0 if the number of argument is correct, otherwise emit an alert and return 1
330 * Fill err_code with an ERR_ALERT and an ERR_FATAL
331 */
332int alertif_too_many_args_idx(int maxarg, int index, const char *file, int linenum, char **args, int *err_code)
333{
334 char *kw = NULL;
335 int i;
336
337 if (!*args[index + maxarg + 1])
338 return 0;
339
340 memprintf(&kw, "%s", args[0]);
341 for (i = 1; i <= index; i++) {
342 memprintf(&kw, "%s %s", kw, args[i]);
343 }
344
345 Alert("parsing [%s:%d] : '%s' cannot handle unexpected argument '%s'.\n", file, linenum, kw, args[index + maxarg + 1]);
346 free(kw);
347 *err_code |= ERR_ALERT | ERR_FATAL;
348 return 1;
349}
350
351/*
352 * same as alertif_too_many_args_idx with a 0 index
353 */
354int alertif_too_many_args(int maxarg, const char *file, int linenum, char **args, int *err_code)
355{
356 return alertif_too_many_args_idx(maxarg, 0, file, linenum, args, err_code);
357}
358
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200359/* Report a warning if a rule is placed after a 'tcp-request content' rule.
360 * Return 1 if the warning has been emitted, otherwise 0.
361 */
362int warnif_rule_after_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
363{
364 if (!LIST_ISEMPTY(&proxy->tcp_req.inspect_rules)) {
365 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request content' rule will still be processed before.\n",
366 file, line, arg);
367 return 1;
368 }
369 return 0;
370}
371
Willy Tarreau61d18892009-03-31 10:49:21 +0200372/* Report a warning if a rule is placed after a 'block' rule.
373 * Return 1 if the warning has been emitted, otherwise 0.
374 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100375int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200376{
Willy Tarreau353bc9f2014-04-28 22:05:31 +0200377 if (!LIST_ISEMPTY(&proxy->block_rules)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200378 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
379 file, line, arg);
380 return 1;
381 }
382 return 0;
383}
384
Willy Tarreau5002f572014-04-23 01:32:02 +0200385/* Report a warning if a rule is placed after an 'http_request' rule.
386 * Return 1 if the warning has been emitted, otherwise 0.
387 */
388int warnif_rule_after_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
389{
390 if (!LIST_ISEMPTY(&proxy->http_req_rules)) {
391 Warning("parsing [%s:%d] : a '%s' rule placed after an 'http-request' rule will still be processed before.\n",
392 file, line, arg);
393 return 1;
394 }
395 return 0;
396}
397
Willy Tarreau61d18892009-03-31 10:49:21 +0200398/* Report a warning if a rule is placed after a reqrewrite rule.
399 * Return 1 if the warning has been emitted, otherwise 0.
400 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100401int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200402{
403 if (proxy->req_exp) {
404 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
405 file, line, arg);
406 return 1;
407 }
408 return 0;
409}
410
411/* Report a warning if a rule is placed after a reqadd rule.
412 * Return 1 if the warning has been emitted, otherwise 0.
413 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100414int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200415{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100416 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200417 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
418 file, line, arg);
419 return 1;
420 }
421 return 0;
422}
423
424/* Report a warning if a rule is placed after a redirect rule.
425 * Return 1 if the warning has been emitted, otherwise 0.
426 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100427int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200428{
429 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
430 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
431 file, line, arg);
432 return 1;
433 }
434 return 0;
435}
436
437/* Report a warning if a rule is placed after a 'use_backend' rule.
438 * Return 1 if the warning has been emitted, otherwise 0.
439 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100440int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200441{
442 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
443 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
444 file, line, arg);
445 return 1;
446 }
447 return 0;
448}
449
Willy Tarreauee445d92014-04-23 01:39:04 +0200450/* Report a warning if a rule is placed after a 'use-server' rule.
451 * Return 1 if the warning has been emitted, otherwise 0.
452 */
453int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line, const char *arg)
454{
455 if (!LIST_ISEMPTY(&proxy->server_rules)) {
456 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use-server' rule will still be processed before.\n",
457 file, line, arg);
458 return 1;
459 }
460 return 0;
461}
462
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200463/* report a warning if a "tcp request connection" rule is dangerously placed */
464int warnif_misplaced_tcp_conn(struct proxy *proxy, const char *file, int line, const char *arg)
465{
466 return warnif_rule_after_tcp_cont(proxy, file, line, arg) ||
467 warnif_rule_after_block(proxy, file, line, arg) ||
468 warnif_rule_after_http_req(proxy, file, line, arg) ||
469 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
470 warnif_rule_after_reqadd(proxy, file, line, arg) ||
471 warnif_rule_after_redirect(proxy, file, line, arg) ||
472 warnif_rule_after_use_backend(proxy, file, line, arg) ||
473 warnif_rule_after_use_server(proxy, file, line, arg);
474}
475
476/* report a warning if a "tcp request content" rule is dangerously placed */
477int warnif_misplaced_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
478{
479 return warnif_rule_after_block(proxy, file, line, arg) ||
480 warnif_rule_after_http_req(proxy, file, line, arg) ||
481 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
482 warnif_rule_after_reqadd(proxy, file, line, arg) ||
483 warnif_rule_after_redirect(proxy, file, line, arg) ||
484 warnif_rule_after_use_backend(proxy, file, line, arg) ||
485 warnif_rule_after_use_server(proxy, file, line, arg);
486}
487
Willy Tarreau61d18892009-03-31 10:49:21 +0200488/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100489int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200490{
Willy Tarreau5002f572014-04-23 01:32:02 +0200491 return warnif_rule_after_http_req(proxy, file, line, arg) ||
492 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
493 warnif_rule_after_reqadd(proxy, file, line, arg) ||
494 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200495 warnif_rule_after_use_backend(proxy, file, line, arg) ||
496 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau5002f572014-04-23 01:32:02 +0200497}
498
499/* report a warning if an http-request rule is dangerously placed */
500int warnif_misplaced_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
501{
Willy Tarreau61d18892009-03-31 10:49:21 +0200502 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
503 warnif_rule_after_reqadd(proxy, file, line, arg) ||
504 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200505 warnif_rule_after_use_backend(proxy, file, line, arg) ||
506 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200507}
508
509/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100510int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200511{
512 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
513 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200514 warnif_rule_after_use_backend(proxy, file, line, arg) ||
515 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200516}
517
518/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100519int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200520{
521 return warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200522 warnif_rule_after_use_backend(proxy, file, line, arg) ||
523 warnif_rule_after_use_server(proxy, file, line, arg);
524}
525
526/* report a warning if a redirect rule is dangerously placed */
527int warnif_misplaced_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
528{
529 return warnif_rule_after_use_backend(proxy, file, line, arg) ||
530 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200531}
532
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100533/* Report it if a request ACL condition uses some keywords that are incompatible
534 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
535 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
536 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100537 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100538static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100539{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100540 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200541 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100542
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100543 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100544 return 0;
545
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100546 acl = acl_cond_conflicts(cond, where);
547 if (acl) {
548 if (acl->name && *acl->name)
549 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
550 file, line, acl->name, sample_ckp_names(where));
551 else
552 Warning("parsing [%s:%d] : anonymous acl will never match because it uses keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200553 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100554 return ERR_WARN;
555 }
556 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100557 return 0;
558
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100559 if (acl->name && *acl->name)
560 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200561 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100562 else
563 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200564 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100565 return ERR_WARN;
566}
567
Willy Tarreaubaaee002006-06-26 02:48:02 +0200568/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200569 * parse a line in a <global> section. Returns the error code, 0 if OK, or
570 * any combination of :
571 * - ERR_ABORT: must abort ASAP
572 * - ERR_FATAL: we can continue parsing but not start the service
573 * - ERR_WARN: a warning has been emitted
574 * - ERR_ALERT: an alert has been emitted
575 * Only the two first ones can stop processing, the two others are just
576 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200577 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200578int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200579{
Willy Tarreau058e9072009-07-20 09:30:05 +0200580 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200581 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200582
583 if (!strcmp(args[0], "global")) { /* new section */
584 /* no option, nothing special to do */
William Lallemand6e62fb62015-04-28 16:55:23 +0200585 alertif_too_many_args(0, file, linenum, args, &err_code);
Willy Tarreau058e9072009-07-20 09:30:05 +0200586 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200587 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200588 else if (!strcmp(args[0], "ca-base")) {
589#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +0200590 if(alertif_too_many_args(1, file, linenum, args, &err_code))
591 goto out;
Emeric Brunc8e8d122012-10-02 18:42:10 +0200592 if (global.ca_base != NULL) {
593 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
594 err_code |= ERR_ALERT;
595 goto out;
596 }
597 if (*(args[1]) == 0) {
598 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
599 err_code |= ERR_ALERT | ERR_FATAL;
600 goto out;
601 }
602 global.ca_base = strdup(args[1]);
603#else
604 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
605 err_code |= ERR_ALERT | ERR_FATAL;
606 goto out;
607#endif
608 }
609 else if (!strcmp(args[0], "crt-base")) {
610#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +0200611 if (alertif_too_many_args(1, file, linenum, args, &err_code))
612 goto out;
Emeric Brunc8e8d122012-10-02 18:42:10 +0200613 if (global.crt_base != NULL) {
614 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
615 err_code |= ERR_ALERT;
616 goto out;
617 }
618 if (*(args[1]) == 0) {
619 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
620 err_code |= ERR_ALERT | ERR_FATAL;
621 goto out;
622 }
623 global.crt_base = strdup(args[1]);
624#else
625 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
626 err_code |= ERR_ALERT | ERR_FATAL;
627 goto out;
628#endif
629 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200630 else if (!strcmp(args[0], "daemon")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200631 if (alertif_too_many_args(0, file, linenum, args, &err_code))
632 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200633 global.mode |= MODE_DAEMON;
634 }
635 else if (!strcmp(args[0], "debug")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200636 if (alertif_too_many_args(0, file, linenum, args, &err_code))
637 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200638 global.mode |= MODE_DEBUG;
639 }
640 else if (!strcmp(args[0], "noepoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200641 if (alertif_too_many_args(0, file, linenum, args, &err_code))
642 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100643 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200644 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200645 else if (!strcmp(args[0], "nokqueue")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200646 if (alertif_too_many_args(0, file, linenum, args, &err_code))
647 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100648 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200649 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200650 else if (!strcmp(args[0], "nopoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200651 if (alertif_too_many_args(0, file, linenum, args, &err_code))
652 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100653 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200654 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100655 else if (!strcmp(args[0], "nosplice")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200656 if (alertif_too_many_args(0, file, linenum, args, &err_code))
657 goto out;
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100658 global.tune.options &= ~GTUNE_USE_SPLICE;
659 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200660 else if (!strcmp(args[0], "nogetaddrinfo")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200661 if (alertif_too_many_args(0, file, linenum, args, &err_code))
662 goto out;
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200663 global.tune.options &= ~GTUNE_USE_GAI;
664 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200665 else if (!strcmp(args[0], "quiet")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200666 if (alertif_too_many_args(0, file, linenum, args, &err_code))
667 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200668 global.mode |= MODE_QUIET;
669 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200670 else if (!strcmp(args[0], "tune.maxpollevents")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200671 if (alertif_too_many_args(1, file, linenum, args, &err_code))
672 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200673 if (global.tune.maxpollevents != 0) {
674 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200675 err_code |= ERR_ALERT;
676 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200677 }
678 if (*(args[1]) == 0) {
679 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200680 err_code |= ERR_ALERT | ERR_FATAL;
681 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200682 }
683 global.tune.maxpollevents = atol(args[1]);
684 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100685 else if (!strcmp(args[0], "tune.maxaccept")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200686 if (alertif_too_many_args(1, file, linenum, args, &err_code))
687 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100688 if (global.tune.maxaccept != 0) {
689 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200690 err_code |= ERR_ALERT;
691 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100692 }
693 if (*(args[1]) == 0) {
694 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200695 err_code |= ERR_ALERT | ERR_FATAL;
696 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100697 }
698 global.tune.maxaccept = atol(args[1]);
699 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200700 else if (!strcmp(args[0], "tune.chksize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200701 if (alertif_too_many_args(1, file, linenum, args, &err_code))
702 goto out;
Willy Tarreau43961d52010-10-04 20:39:20 +0200703 if (*(args[1]) == 0) {
704 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
705 err_code |= ERR_ALERT | ERR_FATAL;
706 goto out;
707 }
708 global.tune.chksize = atol(args[1]);
709 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200710#ifdef USE_OPENSSL
Emeric Brun8dc60392014-05-09 13:52:00 +0200711 else if (!strcmp(args[0], "tune.ssl.force-private-cache")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200712 if (alertif_too_many_args(0, file, linenum, args, &err_code))
713 goto out;
Emeric Brun8dc60392014-05-09 13:52:00 +0200714 global.tune.sslprivatecache = 1;
715 }
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100716 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200717 if (alertif_too_many_args(1, file, linenum, args, &err_code))
718 goto out;
Emeric Brunfc32aca2012-09-03 12:10:29 +0200719 if (*(args[1]) == 0) {
720 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
721 err_code |= ERR_ALERT | ERR_FATAL;
722 goto out;
723 }
724 global.tune.sslcachesize = atol(args[1]);
725 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100726 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
727 unsigned int ssllifetime;
728 const char *res;
729
William Lallemand1a748ae2015-05-19 16:37:23 +0200730 if (alertif_too_many_args(1, file, linenum, args, &err_code))
731 goto out;
Emeric Brun4f65bff2012-11-16 15:11:00 +0100732 if (*(args[1]) == 0) {
733 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
734 err_code |= ERR_ALERT | ERR_FATAL;
735 goto out;
736 }
737
738 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
739 if (res) {
740 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
741 file, linenum, *res, args[0]);
742 err_code |= ERR_ALERT | ERR_FATAL;
743 goto out;
744 }
745
746 global.tune.ssllifetime = ssllifetime;
747 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100748 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200749 if (alertif_too_many_args(1, file, linenum, args, &err_code))
750 goto out;
Willy Tarreaubfd59462013-02-21 07:46:09 +0100751 if (*(args[1]) == 0) {
752 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
753 err_code |= ERR_ALERT | ERR_FATAL;
754 goto out;
755 }
756 global.tune.ssl_max_record = atol(args[1]);
757 }
Remi Gacogne47783ef2015-05-29 15:53:22 +0200758#ifndef OPENSSL_NO_DH
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200759 else if (!strcmp(args[0], "tune.ssl.default-dh-param")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200760 if (alertif_too_many_args(1, file, linenum, args, &err_code))
761 goto out;
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200762 if (*(args[1]) == 0) {
763 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
764 err_code |= ERR_ALERT | ERR_FATAL;
765 goto out;
766 }
767 global.tune.ssl_default_dh_param = atol(args[1]);
768 if (global.tune.ssl_default_dh_param < 1024) {
769 Alert("parsing [%s:%d] : '%s' expects a value >= 1024.\n", file, linenum, args[0]);
770 err_code |= ERR_ALERT | ERR_FATAL;
771 goto out;
772 }
773 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200774#endif
Christopher Faulet31af49d2015-06-09 17:29:50 +0200775 else if (!strcmp(args[0], "tune.ssl.ssl-ctx-cache-size")) {
776 if (alertif_too_many_args(1, file, linenum, args, &err_code))
777 goto out;
778 if (*(args[1]) == 0) {
779 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
780 err_code |= ERR_ALERT | ERR_FATAL;
781 goto out;
782 }
783 global.tune.ssl_ctx_cache = atoi(args[1]);
784 if (global.tune.ssl_ctx_cache < 0) {
785 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
786 file, linenum, args[0]);
787 err_code |= ERR_ALERT | ERR_FATAL;
788 goto out;
789 }
790 }
Remi Gacogne47783ef2015-05-29 15:53:22 +0200791#endif
Willy Tarreau33cb0652014-12-23 22:52:37 +0100792 else if (!strcmp(args[0], "tune.buffers.limit")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200793 if (alertif_too_many_args(1, file, linenum, args, &err_code))
794 goto out;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100795 if (*(args[1]) == 0) {
796 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
797 err_code |= ERR_ALERT | ERR_FATAL;
798 goto out;
799 }
800 global.tune.buf_limit = atol(args[1]);
801 if (global.tune.buf_limit) {
802 if (global.tune.buf_limit < 3)
803 global.tune.buf_limit = 3;
804 if (global.tune.buf_limit <= global.tune.reserved_bufs)
805 global.tune.buf_limit = global.tune.reserved_bufs + 1;
806 }
807 }
Willy Tarreau1058ae72014-12-23 22:40:40 +0100808 else if (!strcmp(args[0], "tune.buffers.reserve")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200809 if (alertif_too_many_args(1, file, linenum, args, &err_code))
810 goto out;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100811 if (*(args[1]) == 0) {
812 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
813 err_code |= ERR_ALERT | ERR_FATAL;
814 goto out;
815 }
816 global.tune.reserved_bufs = atol(args[1]);
817 if (global.tune.reserved_bufs < 2)
818 global.tune.reserved_bufs = 2;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100819 if (global.tune.buf_limit && global.tune.buf_limit <= global.tune.reserved_bufs)
820 global.tune.buf_limit = global.tune.reserved_bufs + 1;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100821 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200822 else if (!strcmp(args[0], "tune.bufsize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200823 if (alertif_too_many_args(1, file, linenum, args, &err_code))
824 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200825 if (*(args[1]) == 0) {
826 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
827 err_code |= ERR_ALERT | ERR_FATAL;
828 goto out;
829 }
830 global.tune.bufsize = atol(args[1]);
Willy Tarreau9b694542015-09-28 13:49:53 +0200831 if (global.tune.bufsize <= 0) {
832 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
833 err_code |= ERR_ALERT | ERR_FATAL;
834 goto out;
835 }
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100836 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100837 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200838 }
839 else if (!strcmp(args[0], "tune.maxrewrite")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200840 if (alertif_too_many_args(1, file, linenum, args, &err_code))
841 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200842 if (*(args[1]) == 0) {
843 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
844 err_code |= ERR_ALERT | ERR_FATAL;
845 goto out;
846 }
847 global.tune.maxrewrite = atol(args[1]);
Willy Tarreau27097842015-09-28 13:53:23 +0200848 if (global.tune.maxrewrite < 0) {
849 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
850 err_code |= ERR_ALERT | ERR_FATAL;
851 goto out;
852 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200853 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100854 else if (!strcmp(args[0], "tune.idletimer")) {
855 unsigned int idle;
856 const char *res;
857
William Lallemand1a748ae2015-05-19 16:37:23 +0200858 if (alertif_too_many_args(1, file, linenum, args, &err_code))
859 goto out;
Willy Tarreau7e312732014-02-12 16:35:14 +0100860 if (*(args[1]) == 0) {
861 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
862 err_code |= ERR_ALERT | ERR_FATAL;
863 goto out;
864 }
865
866 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
867 if (res) {
868 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
869 file, linenum, *res, args[0]);
870 err_code |= ERR_ALERT | ERR_FATAL;
871 goto out;
872 }
873
874 if (idle > 65535) {
875 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
876 err_code |= ERR_ALERT | ERR_FATAL;
877 goto out;
878 }
879 global.tune.idle_timer = idle;
880 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100881 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200882 if (alertif_too_many_args(1, file, linenum, args, &err_code))
883 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100884 if (global.tune.client_rcvbuf != 0) {
885 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
886 err_code |= ERR_ALERT;
887 goto out;
888 }
889 if (*(args[1]) == 0) {
890 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
891 err_code |= ERR_ALERT | ERR_FATAL;
892 goto out;
893 }
894 global.tune.client_rcvbuf = atol(args[1]);
895 }
896 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200897 if (alertif_too_many_args(1, file, linenum, args, &err_code))
898 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100899 if (global.tune.server_rcvbuf != 0) {
900 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
901 err_code |= ERR_ALERT;
902 goto out;
903 }
904 if (*(args[1]) == 0) {
905 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
906 err_code |= ERR_ALERT | ERR_FATAL;
907 goto out;
908 }
909 global.tune.server_rcvbuf = atol(args[1]);
910 }
911 else if (!strcmp(args[0], "tune.sndbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200912 if (alertif_too_many_args(1, file, linenum, args, &err_code))
913 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100914 if (global.tune.client_sndbuf != 0) {
915 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
916 err_code |= ERR_ALERT;
917 goto out;
918 }
919 if (*(args[1]) == 0) {
920 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
921 err_code |= ERR_ALERT | ERR_FATAL;
922 goto out;
923 }
924 global.tune.client_sndbuf = atol(args[1]);
925 }
926 else if (!strcmp(args[0], "tune.sndbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200927 if (alertif_too_many_args(1, file, linenum, args, &err_code))
928 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100929 if (global.tune.server_sndbuf != 0) {
930 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
931 err_code |= ERR_ALERT;
932 goto out;
933 }
934 if (*(args[1]) == 0) {
935 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
936 err_code |= ERR_ALERT | ERR_FATAL;
937 goto out;
938 }
939 global.tune.server_sndbuf = atol(args[1]);
940 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200941 else if (!strcmp(args[0], "tune.pipesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200942 if (alertif_too_many_args(1, file, linenum, args, &err_code))
943 goto out;
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200944 if (*(args[1]) == 0) {
945 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
946 err_code |= ERR_ALERT | ERR_FATAL;
947 goto out;
948 }
949 global.tune.pipesize = atol(args[1]);
950 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100951 else if (!strcmp(args[0], "tune.http.cookielen")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200952 if (alertif_too_many_args(1, file, linenum, args, &err_code))
953 goto out;
Willy Tarreau193b8c62012-11-22 00:17:38 +0100954 if (*(args[1]) == 0) {
955 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
956 err_code |= ERR_ALERT | ERR_FATAL;
957 goto out;
958 }
959 global.tune.cookie_len = atol(args[1]) + 1;
960 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200961 else if (!strcmp(args[0], "tune.http.maxhdr")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200962 if (alertif_too_many_args(1, file, linenum, args, &err_code))
963 goto out;
Willy Tarreauac1932d2011-10-24 19:14:41 +0200964 if (*(args[1]) == 0) {
965 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
966 err_code |= ERR_ALERT | ERR_FATAL;
967 goto out;
968 }
969 global.tune.max_http_hdr = atol(args[1]);
970 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100971 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
972#ifdef USE_ZLIB
William Lallemand1a748ae2015-05-19 16:37:23 +0200973 if (alertif_too_many_args(1, file, linenum, args, &err_code))
974 goto out;
William Lallemanda509e4c2012-11-07 16:54:34 +0100975 if (*args[1]) {
976 global.tune.zlibmemlevel = atoi(args[1]);
977 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
978 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
979 file, linenum, args[0]);
980 err_code |= ERR_ALERT | ERR_FATAL;
981 goto out;
982 }
983 } else {
984 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
985 file, linenum, args[0]);
986 err_code |= ERR_ALERT | ERR_FATAL;
987 goto out;
988 }
989#else
990 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
991 err_code |= ERR_ALERT | ERR_FATAL;
992 goto out;
993#endif
994 }
995 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
996#ifdef USE_ZLIB
William Lallemand1a748ae2015-05-19 16:37:23 +0200997 if (alertif_too_many_args(1, file, linenum, args, &err_code))
998 goto out;
William Lallemanda509e4c2012-11-07 16:54:34 +0100999 if (*args[1]) {
1000 global.tune.zlibwindowsize = atoi(args[1]);
1001 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
1002 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
1003 file, linenum, args[0]);
1004 err_code |= ERR_ALERT | ERR_FATAL;
1005 goto out;
1006 }
1007 } else {
1008 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
1009 file, linenum, args[0]);
1010 err_code |= ERR_ALERT | ERR_FATAL;
1011 goto out;
1012 }
1013#else
1014 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1015 err_code |= ERR_ALERT | ERR_FATAL;
1016 goto out;
1017#endif
1018 }
William Lallemandf3747832012-11-09 12:33:10 +01001019 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001020 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1021 goto out;
William Lallemandf3747832012-11-09 12:33:10 +01001022 if (*args[1]) {
1023 global.tune.comp_maxlevel = atoi(args[1]);
1024 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
1025 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1026 file, linenum, args[0]);
1027 err_code |= ERR_ALERT | ERR_FATAL;
1028 goto out;
1029 }
1030 } else {
1031 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1032 file, linenum, args[0]);
1033 err_code |= ERR_ALERT | ERR_FATAL;
1034 goto out;
1035 }
1036 }
Willy Tarreauf3045d22015-04-29 16:24:50 +02001037 else if (!strcmp(args[0], "tune.pattern.cache-size")) {
1038 if (*args[1]) {
1039 global.tune.pattern_cache = atoi(args[1]);
1040 if (global.tune.pattern_cache < 0) {
1041 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
1042 file, linenum, args[0]);
1043 err_code |= ERR_ALERT | ERR_FATAL;
1044 goto out;
1045 }
1046 } else {
1047 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
1048 file, linenum, args[0]);
1049 err_code |= ERR_ALERT | ERR_FATAL;
1050 goto out;
1051 }
1052 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001053 else if (!strcmp(args[0], "uid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001054 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1055 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001056 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001057 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001058 err_code |= ERR_ALERT;
1059 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001060 }
1061 if (*(args[1]) == 0) {
1062 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001063 err_code |= ERR_ALERT | ERR_FATAL;
1064 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001065 }
1066 global.uid = atol(args[1]);
1067 }
1068 else if (!strcmp(args[0], "gid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001069 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1070 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001071 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001072 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001073 err_code |= ERR_ALERT;
1074 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001075 }
1076 if (*(args[1]) == 0) {
1077 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001078 err_code |= ERR_ALERT | ERR_FATAL;
1079 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001080 }
1081 global.gid = atol(args[1]);
1082 }
Simon Horman98637e52014-06-20 12:30:16 +09001083 else if (!strcmp(args[0], "external-check")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001084 if (alertif_too_many_args(0, file, linenum, args, &err_code))
1085 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09001086 global.external_check = 1;
1087 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001088 /* user/group name handling */
1089 else if (!strcmp(args[0], "user")) {
1090 struct passwd *ha_user;
William Lallemand1a748ae2015-05-19 16:37:23 +02001091 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1092 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001093 if (global.uid != 0) {
1094 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001095 err_code |= ERR_ALERT;
1096 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001097 }
1098 errno = 0;
1099 ha_user = getpwnam(args[1]);
1100 if (ha_user != NULL) {
1101 global.uid = (int)ha_user->pw_uid;
1102 }
1103 else {
1104 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +02001105 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001106 }
1107 }
1108 else if (!strcmp(args[0], "group")) {
1109 struct group *ha_group;
William Lallemand1a748ae2015-05-19 16:37:23 +02001110 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1111 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001112 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02001113 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001114 err_code |= ERR_ALERT;
1115 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001116 }
1117 errno = 0;
1118 ha_group = getgrnam(args[1]);
1119 if (ha_group != NULL) {
1120 global.gid = (int)ha_group->gr_gid;
1121 }
1122 else {
1123 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +02001124 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001125 }
1126 }
1127 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +02001128 else if (!strcmp(args[0], "nbproc")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001129 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1130 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001131 if (*(args[1]) == 0) {
1132 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001133 err_code |= ERR_ALERT | ERR_FATAL;
1134 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001135 }
1136 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001137 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
1138 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
1139 file, linenum, args[0], LONGBITS, global.nbproc);
1140 err_code |= ERR_ALERT | ERR_FATAL;
1141 goto out;
1142 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001143 }
1144 else if (!strcmp(args[0], "maxconn")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001145 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1146 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001147 if (global.maxconn != 0) {
1148 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001149 err_code |= ERR_ALERT;
1150 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001151 }
1152 if (*(args[1]) == 0) {
1153 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001154 err_code |= ERR_ALERT | ERR_FATAL;
1155 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001156 }
1157 global.maxconn = atol(args[1]);
1158#ifdef SYSTEM_MAXCONN
1159 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
1160 Alert("parsing [%s:%d] : maxconn value %d too high for this system.\nLimiting to %d. Please use '-n' to force the value.\n", file, linenum, global.maxconn, DEFAULT_MAXCONN);
1161 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +02001162 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001163 }
1164#endif /* SYSTEM_MAXCONN */
1165 }
Willy Tarreau403edff2012-09-06 11:58:37 +02001166 else if (!strcmp(args[0], "maxsslconn")) {
1167#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001168 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1169 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001170 if (*(args[1]) == 0) {
1171 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1172 err_code |= ERR_ALERT | ERR_FATAL;
1173 goto out;
1174 }
1175 global.maxsslconn = atol(args[1]);
1176#else
Emeric Brun0914df82012-10-02 18:45:42 +02001177 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1178 err_code |= ERR_ALERT | ERR_FATAL;
1179 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001180#endif
1181 }
Willy Tarreau610f04b2014-02-13 11:36:41 +01001182 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
1183#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001184 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1185 goto out;
Willy Tarreau610f04b2014-02-13 11:36:41 +01001186 if (*(args[1]) == 0) {
1187 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1188 err_code |= ERR_ALERT | ERR_FATAL;
1189 goto out;
1190 }
1191 free(global.listen_default_ciphers);
1192 global.listen_default_ciphers = strdup(args[1]);
1193#else
1194 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1195 err_code |= ERR_ALERT | ERR_FATAL;
1196 goto out;
1197#endif
1198 }
1199 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
1200#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001201 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1202 goto out;
Willy Tarreau610f04b2014-02-13 11:36:41 +01001203 if (*(args[1]) == 0) {
1204 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1205 err_code |= ERR_ALERT | ERR_FATAL;
1206 goto out;
1207 }
1208 free(global.connect_default_ciphers);
1209 global.connect_default_ciphers = strdup(args[1]);
1210#else
1211 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1212 err_code |= ERR_ALERT | ERR_FATAL;
1213 goto out;
1214#endif
1215 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02001216#ifdef USE_OPENSSL
1217#ifndef OPENSSL_NO_DH
1218 else if (!strcmp(args[0], "ssl-dh-param-file")) {
1219 if (*(args[1]) == 0) {
1220 Alert("parsing [%s:%d] : '%s' expects a file path as an argument.\n", file, linenum, args[0]);
1221 err_code |= ERR_ALERT | ERR_FATAL;
1222 goto out;
1223 }
1224 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
1225 Alert("parsing [%s:%d] : '%s': unable to load DH parameters from file <%s>.\n", file, linenum, args[0], args[1]);
1226 err_code |= ERR_ALERT | ERR_FATAL;
1227 goto out;
1228 }
1229 }
1230#endif
1231#endif
Emeric Brun850efd52014-01-29 12:24:34 +01001232 else if (!strcmp(args[0], "ssl-server-verify")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001233 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1234 goto out;
Emeric Brun850efd52014-01-29 12:24:34 +01001235 if (*(args[1]) == 0) {
1236 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1237 err_code |= ERR_ALERT | ERR_FATAL;
1238 goto out;
1239 }
1240 if (strcmp(args[1],"none") == 0)
1241 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1242 else if (strcmp(args[1],"required") == 0)
1243 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1244 else {
1245 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1246 err_code |= ERR_ALERT | ERR_FATAL;
1247 goto out;
1248 }
1249 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001250 else if (!strcmp(args[0], "maxconnrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001251 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1252 goto out;
Willy Tarreau81c25d02011-09-07 15:17:21 +02001253 if (global.cps_lim != 0) {
1254 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1255 err_code |= ERR_ALERT;
1256 goto out;
1257 }
1258 if (*(args[1]) == 0) {
1259 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1260 err_code |= ERR_ALERT | ERR_FATAL;
1261 goto out;
1262 }
1263 global.cps_lim = atol(args[1]);
1264 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001265 else if (!strcmp(args[0], "maxsessrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001266 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1267 goto out;
Willy Tarreau93e7c002013-10-07 18:51:07 +02001268 if (global.sps_lim != 0) {
1269 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1270 err_code |= ERR_ALERT;
1271 goto out;
1272 }
1273 if (*(args[1]) == 0) {
1274 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1275 err_code |= ERR_ALERT | ERR_FATAL;
1276 goto out;
1277 }
1278 global.sps_lim = atol(args[1]);
1279 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001280 else if (!strcmp(args[0], "maxsslrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001281 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1282 goto out;
Willy Tarreaue43d5322013-10-07 20:01:52 +02001283 if (global.ssl_lim != 0) {
1284 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1285 err_code |= ERR_ALERT;
1286 goto out;
1287 }
1288 if (*(args[1]) == 0) {
1289 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1290 err_code |= ERR_ALERT | ERR_FATAL;
1291 goto out;
1292 }
1293 global.ssl_lim = atol(args[1]);
1294 }
William Lallemandd85f9172012-11-09 17:05:39 +01001295 else if (!strcmp(args[0], "maxcomprate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001296 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1297 goto out;
William Lallemandd85f9172012-11-09 17:05:39 +01001298 if (*(args[1]) == 0) {
1299 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1300 err_code |= ERR_ALERT | ERR_FATAL;
1301 goto out;
1302 }
1303 global.comp_rate_lim = atoi(args[1]) * 1024;
1304 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001305 else if (!strcmp(args[0], "maxpipes")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001306 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1307 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001308 if (global.maxpipes != 0) {
1309 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001310 err_code |= ERR_ALERT;
1311 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001312 }
1313 if (*(args[1]) == 0) {
1314 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001315 err_code |= ERR_ALERT | ERR_FATAL;
1316 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001317 }
1318 global.maxpipes = atol(args[1]);
1319 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001320 else if (!strcmp(args[0], "maxzlibmem")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001321 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1322 goto out;
William Lallemand9d5f5482012-11-07 16:12:57 +01001323 if (*(args[1]) == 0) {
1324 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1325 err_code |= ERR_ALERT | ERR_FATAL;
1326 goto out;
1327 }
William Lallemande3a7d992012-11-20 11:25:20 +01001328 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001329 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001330 else if (!strcmp(args[0], "maxcompcpuusage")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001331 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1332 goto out;
William Lallemand072a2bf2012-11-20 17:01:01 +01001333 if (*(args[1]) == 0) {
1334 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1335 err_code |= ERR_ALERT | ERR_FATAL;
1336 goto out;
1337 }
1338 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001339 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001340 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1341 err_code |= ERR_ALERT | ERR_FATAL;
1342 goto out;
1343 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001344 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001345
Willy Tarreaubaaee002006-06-26 02:48:02 +02001346 else if (!strcmp(args[0], "ulimit-n")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001347 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1348 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001349 if (global.rlimit_nofile != 0) {
1350 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001351 err_code |= ERR_ALERT;
1352 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001353 }
1354 if (*(args[1]) == 0) {
1355 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001356 err_code |= ERR_ALERT | ERR_FATAL;
1357 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001358 }
1359 global.rlimit_nofile = atol(args[1]);
1360 }
1361 else if (!strcmp(args[0], "chroot")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001362 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1363 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001364 if (global.chroot != NULL) {
1365 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001366 err_code |= ERR_ALERT;
1367 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001368 }
1369 if (*(args[1]) == 0) {
1370 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001371 err_code |= ERR_ALERT | ERR_FATAL;
1372 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001373 }
1374 global.chroot = strdup(args[1]);
1375 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001376 else if (!strcmp(args[0], "description")) {
1377 int i, len=0;
1378 char *d;
1379
1380 if (!*args[1]) {
1381 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1382 file, linenum, args[0]);
1383 err_code |= ERR_ALERT | ERR_FATAL;
1384 goto out;
1385 }
1386
Willy Tarreau348acfe2014-04-14 15:00:39 +02001387 for (i = 1; *args[i]; i++)
1388 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001389
1390 if (global.desc)
1391 free(global.desc);
1392
1393 global.desc = d = (char *)calloc(1, len);
1394
Willy Tarreau348acfe2014-04-14 15:00:39 +02001395 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1396 for (i = 2; *args[i]; i++)
1397 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001398 }
1399 else if (!strcmp(args[0], "node")) {
1400 int i;
1401 char c;
1402
William Lallemand1a748ae2015-05-19 16:37:23 +02001403 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1404 goto out;
1405
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001406 for (i=0; args[1][i]; i++) {
1407 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001408 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1409 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001410 break;
1411 }
1412
1413 if (!i || args[1][i]) {
1414 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1415 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1416 file, linenum, args[0]);
1417 err_code |= ERR_ALERT | ERR_FATAL;
1418 goto out;
1419 }
1420
1421 if (global.node)
1422 free(global.node);
1423
1424 global.node = strdup(args[1]);
1425 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001426 else if (!strcmp(args[0], "pidfile")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001427 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1428 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001429 if (global.pidfile != NULL) {
1430 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001431 err_code |= ERR_ALERT;
1432 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001433 }
1434 if (*(args[1]) == 0) {
1435 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001436 err_code |= ERR_ALERT | ERR_FATAL;
1437 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001438 }
1439 global.pidfile = strdup(args[1]);
1440 }
Emeric Bruned760922010-10-22 17:59:25 +02001441 else if (!strcmp(args[0], "unix-bind")) {
1442 int cur_arg = 1;
1443 while (*(args[cur_arg])) {
1444 if (!strcmp(args[cur_arg], "prefix")) {
1445 if (global.unix_bind.prefix != NULL) {
1446 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1447 err_code |= ERR_ALERT;
1448 cur_arg += 2;
1449 continue;
1450 }
1451
1452 if (*(args[cur_arg+1]) == 0) {
1453 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1454 err_code |= ERR_ALERT | ERR_FATAL;
1455 goto out;
1456 }
1457 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1458 cur_arg += 2;
1459 continue;
1460 }
1461
1462 if (!strcmp(args[cur_arg], "mode")) {
1463
1464 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1465 cur_arg += 2;
1466 continue;
1467 }
1468
1469 if (!strcmp(args[cur_arg], "uid")) {
1470
1471 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1472 cur_arg += 2;
1473 continue;
1474 }
1475
1476 if (!strcmp(args[cur_arg], "gid")) {
1477
1478 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1479 cur_arg += 2;
1480 continue;
1481 }
1482
1483 if (!strcmp(args[cur_arg], "user")) {
1484 struct passwd *user;
1485
1486 user = getpwnam(args[cur_arg + 1]);
1487 if (!user) {
1488 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1489 file, linenum, args[0], args[cur_arg + 1 ]);
1490 err_code |= ERR_ALERT | ERR_FATAL;
1491 goto out;
1492 }
1493
1494 global.unix_bind.ux.uid = user->pw_uid;
1495 cur_arg += 2;
1496 continue;
1497 }
1498
1499 if (!strcmp(args[cur_arg], "group")) {
1500 struct group *group;
1501
1502 group = getgrnam(args[cur_arg + 1]);
1503 if (!group) {
1504 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1505 file, linenum, args[0], args[cur_arg + 1 ]);
1506 err_code |= ERR_ALERT | ERR_FATAL;
1507 goto out;
1508 }
1509
1510 global.unix_bind.ux.gid = group->gr_gid;
1511 cur_arg += 2;
1512 continue;
1513 }
1514
Willy Tarreaub48f9582011-09-05 01:17:06 +02001515 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001516 file, linenum, args[0]);
1517 err_code |= ERR_ALERT | ERR_FATAL;
1518 goto out;
1519 }
1520 }
William Lallemand0f99e342011-10-12 17:50:54 +02001521 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1522 /* delete previous herited or defined syslog servers */
1523 struct logsrv *back;
1524 struct logsrv *tmp;
1525
1526 if (*(args[1]) != 0) {
1527 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1528 err_code |= ERR_ALERT | ERR_FATAL;
1529 goto out;
1530 }
1531
1532 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1533 LIST_DEL(&tmp->list);
1534 free(tmp);
1535 }
1536 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001537 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001538 struct sockaddr_storage *sk;
1539 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001540 struct logsrv *logsrv;
Willy Tarreau18324f52014-06-27 18:10:07 +02001541 int arg = 0;
1542 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001543
William Lallemand1a748ae2015-05-19 16:37:23 +02001544 if (alertif_too_many_args(8, file, linenum, args, &err_code)) /* does not strictly check optional arguments */
1545 goto out;
1546
Willy Tarreaubaaee002006-06-26 02:48:02 +02001547 if (*(args[1]) == 0 || *(args[2]) == 0) {
1548 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001549 err_code |= ERR_ALERT | ERR_FATAL;
1550 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001551 }
William Lallemand0f99e342011-10-12 17:50:54 +02001552
1553 logsrv = calloc(1, sizeof(struct logsrv));
1554
Willy Tarreau18324f52014-06-27 18:10:07 +02001555 /* just after the address, a length may be specified */
1556 if (strcmp(args[arg+2], "len") == 0) {
1557 len = atoi(args[arg+3]);
1558 if (len < 80 || len > 65535) {
1559 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1560 file, linenum, args[arg+3]);
1561 err_code |= ERR_ALERT | ERR_FATAL;
1562 goto out;
1563 }
1564 logsrv->maxlen = len;
1565
1566 /* skip these two args */
1567 arg += 2;
1568 }
1569 else
1570 logsrv->maxlen = MAX_SYSLOG_LEN;
1571
1572 if (logsrv->maxlen > global.max_syslog_len) {
1573 global.max_syslog_len = logsrv->maxlen;
Dragan Dosen59cee972015-09-19 22:09:02 +02001574 logheader = realloc(logheader, global.max_syslog_len + 1);
Dragan Dosen1322d092015-09-22 16:05:32 +02001575 logheader_rfc5424 = realloc(logheader_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02001576 logline = realloc(logline, global.max_syslog_len + 1);
Dragan Dosen0b85ece2015-09-25 19:17:44 +02001577 logline_rfc5424 = realloc(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02001578 }
1579
Dragan Dosen1322d092015-09-22 16:05:32 +02001580 /* after the length, a format may be specified */
1581 if (strcmp(args[arg+2], "format") == 0) {
1582 logsrv->format = get_log_format(args[arg+3]);
1583 if (logsrv->format < 0) {
1584 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
1585 err_code |= ERR_ALERT | ERR_FATAL;
1586 goto out;
1587 }
1588
1589 /* skip these two args */
1590 arg += 2;
1591 }
1592
William Lallemand1a748ae2015-05-19 16:37:23 +02001593 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
1594 goto out;
1595
Willy Tarreau18324f52014-06-27 18:10:07 +02001596 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001597 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001598 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001599 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001600 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001601 }
1602
William Lallemand0f99e342011-10-12 17:50:54 +02001603 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02001604 if (*(args[arg+3])) {
1605 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001606 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001607 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001608 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001609 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001610 }
1611 }
1612
William Lallemand0f99e342011-10-12 17:50:54 +02001613 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02001614 if (*(args[arg+4])) {
1615 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001616 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001617 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001618 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001619 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001620 }
1621 }
1622
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02001623 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001624 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001625 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001626 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001627 free(logsrv);
1628 goto out;
1629 }
1630 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001631
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001632 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001633 if (port1 != port2) {
1634 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1635 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001636 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001637 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001638 goto out;
1639 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001640
William Lallemand0f99e342011-10-12 17:50:54 +02001641 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001642 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001643 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001644 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001645
William Lallemand0f99e342011-10-12 17:50:54 +02001646 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001647 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001648 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1649 char *name;
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001650
1651 if (global.log_send_hostname != NULL) {
1652 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1653 err_code |= ERR_ALERT;
1654 goto out;
1655 }
1656
1657 if (*(args[1]))
1658 name = args[1];
1659 else
1660 name = hostname;
1661
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001662 free(global.log_send_hostname);
Dragan Dosenc8cfa7b2015-09-28 13:28:21 +02001663 global.log_send_hostname = strdup(name);
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001664 }
Baptiste Assmann6bc89362015-08-23 09:22:25 +02001665 else if (!strcmp(args[0], "server-state-base")) { /* path base where HAProxy can find server state files */
1666 if (global.server_state_base != NULL) {
1667 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1668 err_code |= ERR_ALERT;
1669 goto out;
1670 }
1671
1672 if (!*(args[1])) {
1673 Alert("parsing [%s:%d] : '%s' expects one argument: a directory path.\n", file, linenum, args[0]);
1674 err_code |= ERR_FATAL;
1675 goto out;
1676 }
1677
1678 global.server_state_base = strdup(args[1]);
1679 }
Baptiste Assmanne0882262015-08-23 09:54:31 +02001680 else if (!strcmp(args[0], "server-state-file")) { /* path to the file where HAProxy can load the server states */
1681 if (global.server_state_file != NULL) {
1682 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1683 err_code |= ERR_ALERT;
1684 goto out;
1685 }
1686
1687 if (!*(args[1])) {
1688 Alert("parsing [%s:%d] : '%s' expect one argument: a file path.\n", file, linenum, args[0]);
1689 err_code |= ERR_FATAL;
1690 goto out;
1691 }
1692
1693 global.server_state_file = strdup(args[1]);
1694 }
Kevinm48936af2010-12-22 16:08:21 +00001695 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
William Lallemand1a748ae2015-05-19 16:37:23 +02001696 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1697 goto out;
Kevinm48936af2010-12-22 16:08:21 +00001698 if (*(args[1]) == 0) {
1699 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1700 err_code |= ERR_ALERT | ERR_FATAL;
1701 goto out;
1702 }
Dragan Dosen43885c72015-10-01 13:18:13 +02001703 chunk_destroy(&global.log_tag);
1704 chunk_initstr(&global.log_tag, strdup(args[1]));
Kevinm48936af2010-12-22 16:08:21 +00001705 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001706 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
William Lallemand1a748ae2015-05-19 16:37:23 +02001707 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1708 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001709 if (global.spread_checks != 0) {
1710 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001711 err_code |= ERR_ALERT;
1712 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001713 }
1714 if (*(args[1]) == 0) {
1715 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001716 err_code |= ERR_ALERT | ERR_FATAL;
1717 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001718 }
1719 global.spread_checks = atol(args[1]);
1720 if (global.spread_checks < 0 || global.spread_checks > 50) {
1721 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001722 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001723 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001724 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001725 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1726 const char *err;
1727 unsigned int val;
1728
William Lallemand1a748ae2015-05-19 16:37:23 +02001729 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1730 goto out;
Willy Tarreau1746eec2014-04-25 10:46:47 +02001731 if (*(args[1]) == 0) {
1732 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1733 err_code |= ERR_ALERT | ERR_FATAL;
1734 goto out;
1735 }
1736
1737 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1738 if (err) {
1739 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1740 err_code |= ERR_ALERT | ERR_FATAL;
1741 }
1742 global.max_spread_checks = val;
1743 if (global.max_spread_checks < 0) {
1744 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1745 err_code |= ERR_ALERT | ERR_FATAL;
1746 }
1747 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001748 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1749#ifdef USE_CPU_AFFINITY
1750 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001751 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001752 unsigned long cpus = 0;
1753
1754 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001755 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001756 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001757 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001758 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001759 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001760 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001761 proc = atol(args[1]);
1762 if (proc >= 1 && proc <= LONGBITS)
1763 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001764 }
1765
1766 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001767 Alert("parsing [%s:%d]: %s expects a process number including 'all', 'odd', 'even', or a number from 1 to %d, followed by a list of CPU ranges with numbers from 0 to %d.\n",
1768 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001769 err_code |= ERR_ALERT | ERR_FATAL;
1770 goto out;
1771 }
1772
1773 cur_arg = 2;
1774 while (*args[cur_arg]) {
1775 unsigned int low, high;
1776
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001777 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001778 char *dash = strchr(args[cur_arg], '-');
1779
1780 low = high = str2uic(args[cur_arg]);
1781 if (dash)
1782 high = str2uic(dash + 1);
1783
1784 if (high < low) {
1785 unsigned int swap = low;
1786 low = high;
1787 high = swap;
1788 }
1789
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001790 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001791 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001792 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001793 err_code |= ERR_ALERT | ERR_FATAL;
1794 goto out;
1795 }
1796
1797 while (low <= high)
1798 cpus |= 1UL << low++;
1799 }
1800 else {
1801 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1802 file, linenum, args[0], args[cur_arg]);
1803 err_code |= ERR_ALERT | ERR_FATAL;
1804 goto out;
1805 }
1806 cur_arg++;
1807 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001808 for (i = 0; i < LONGBITS; i++)
1809 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001810 global.cpu_map[i] = cpus;
1811#else
1812 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1813 err_code |= ERR_ALERT | ERR_FATAL;
1814 goto out;
1815#endif
1816 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001817 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001818 struct cfg_kw_list *kwl;
1819 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001820 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001821
1822 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1823 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1824 if (kwl->kw[index].section != CFG_GLOBAL)
1825 continue;
1826 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001827 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001828 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001829 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001830 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001831 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001832 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001833 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001834 err_code |= ERR_WARN;
1835 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001836 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001837 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001838 }
1839 }
1840 }
1841
Willy Tarreaubaaee002006-06-26 02:48:02 +02001842 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001843 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001844 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001845
Willy Tarreau058e9072009-07-20 09:30:05 +02001846 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001847 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001848 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001849}
1850
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001851void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001852{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001853 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001854 defproxy.mode = PR_MODE_TCP;
1855 defproxy.state = PR_STNEW;
1856 defproxy.maxconn = cfg_maxpconn;
1857 defproxy.conn_retries = CONN_RETRIES;
Joseph Lynch726ab712015-05-11 23:25:34 -07001858 defproxy.redispatch_after = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001859
Simon Horman66183002013-02-23 10:16:43 +09001860 defproxy.defsrv.check.inter = DEF_CHKINTR;
1861 defproxy.defsrv.check.fastinter = 0;
1862 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001863 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1864 defproxy.defsrv.agent.fastinter = 0;
1865 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001866 defproxy.defsrv.check.rise = DEF_RISETIME;
1867 defproxy.defsrv.check.fall = DEF_FALLTIME;
1868 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1869 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001870 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001871 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001872 defproxy.defsrv.maxqueue = 0;
1873 defproxy.defsrv.minconn = 0;
1874 defproxy.defsrv.maxconn = 0;
1875 defproxy.defsrv.slowstart = 0;
1876 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1877 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1878 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Simon Horman64e34162015-02-06 11:11:57 +09001879
1880 defproxy.email_alert.level = LOG_ALERT;
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02001881 defproxy.load_server_state_from_file = PR_SRV_STATE_FILE_UNSPEC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001882}
1883
Willy Tarreauade5ec42010-01-28 19:33:49 +01001884
Willy Tarreau63af98d2014-05-18 08:11:41 +02001885/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1886 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1887 * ERR_FATAL in case of error.
1888 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001889static int create_cond_regex_rule(const char *file, int line,
1890 struct proxy *px, int dir, int action, int flags,
1891 const char *cmd, const char *reg, const char *repl,
1892 const char **cond_start)
1893{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001894 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001895 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001896 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001897 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001898 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001899 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001900 int cs;
1901 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001902
1903 if (px == &defproxy) {
1904 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001905 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001906 goto err;
1907 }
1908
1909 if (*reg == 0) {
1910 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001911 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001912 goto err;
1913 }
1914
1915 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001916 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001917
Willy Tarreau5321c422010-01-28 20:35:13 +01001918 if (cond_start &&
1919 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001920 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1921 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1922 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001923 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001924 goto err;
1925 }
1926 }
1927 else if (cond_start && **cond_start) {
1928 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1929 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001930 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001931 goto err;
1932 }
1933
Willy Tarreau63af98d2014-05-18 08:11:41 +02001934 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001935 (dir == SMP_OPT_DIR_REQ) ?
1936 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1937 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1938 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001939
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001940 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001941 if (!preg) {
1942 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001943 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001944 goto err;
1945 }
1946
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001947 cs = !(flags & REG_ICASE);
1948 cap = !(flags & REG_NOSUB);
1949 error = NULL;
1950 if (!regex_comp(reg, preg, cs, cap, &error)) {
1951 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1952 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001953 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001954 goto err;
1955 }
1956
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001957 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001958 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001959 if (repl && err) {
1960 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1961 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001962 ret_code |= ERR_ALERT | ERR_FATAL;
1963 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001964 }
1965
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001966 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001967 ret_code |= ERR_WARN;
1968
1969 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001970
Willy Tarreau63af98d2014-05-18 08:11:41 +02001971 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001972 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001973 err:
1974 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001975 free(errmsg);
1976 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001977}
1978
Willy Tarreaubaaee002006-06-26 02:48:02 +02001979/*
William Lallemand51097192015-04-14 16:35:22 +02001980 * Parse a line in a <listen>, <frontend> or <backend> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001981 * Returns the error code, 0 if OK, or any combination of :
1982 * - ERR_ABORT: must abort ASAP
1983 * - ERR_FATAL: we can continue parsing but not start the service
1984 * - ERR_WARN: a warning has been emitted
1985 * - ERR_ALERT: an alert has been emitted
1986 * Only the two first ones can stop processing, the two others are just
1987 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001988 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001989int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1990{
1991 static struct peers *curpeers = NULL;
1992 struct peer *newpeer = NULL;
1993 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001994 struct bind_conf *bind_conf;
1995 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001996 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001997 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001998
1999 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002000 if (!*args[1]) {
2001 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01002002 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002003 goto out;
2004 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002005
William Lallemand6e62fb62015-04-28 16:55:23 +02002006 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2007 goto out;
2008
Emeric Brun32da3c42010-09-23 18:39:19 +02002009 err = invalid_char(args[1]);
2010 if (err) {
2011 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2012 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01002013 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002014 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002015 }
2016
2017 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
2018 /*
2019 * If there are two proxies with the same name only following
2020 * combinations are allowed:
2021 */
2022 if (strcmp(curpeers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002023 Alert("Parsing [%s:%d]: peers section '%s' has the same name as another peers section declared at %s:%d.\n",
Emeric Brun32da3c42010-09-23 18:39:19 +02002024 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002025 err_code |= ERR_ALERT | ERR_FATAL;
Emeric Brun32da3c42010-09-23 18:39:19 +02002026 }
2027 }
2028
2029 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
2030 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2031 err_code |= ERR_ALERT | ERR_ABORT;
2032 goto out;
2033 }
2034
2035 curpeers->next = peers;
2036 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002037 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002038 curpeers->conf.line = linenum;
2039 curpeers->last_change = now.tv_sec;
2040 curpeers->id = strdup(args[1]);
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002041 curpeers->state = PR_STNEW;
Emeric Brun32da3c42010-09-23 18:39:19 +02002042 }
2043 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01002044 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01002045 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002046 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02002047
2048 if (!*args[2]) {
2049 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2050 file, linenum, args[0]);
2051 err_code |= ERR_ALERT | ERR_FATAL;
2052 goto out;
2053 }
2054
2055 err = invalid_char(args[1]);
2056 if (err) {
2057 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2058 file, linenum, *err, args[1]);
2059 err_code |= ERR_ALERT | ERR_FATAL;
2060 goto out;
2061 }
2062
2063 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
2064 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2065 err_code |= ERR_ALERT | ERR_ABORT;
2066 goto out;
2067 }
2068
2069 /* the peers are linked backwards first */
2070 curpeers->count++;
2071 newpeer->next = curpeers->remote;
2072 curpeers->remote = newpeer;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002073 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002074 newpeer->conf.line = linenum;
2075
2076 newpeer->last_change = now.tv_sec;
2077 newpeer->id = strdup(args[1]);
2078
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002079 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002080 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01002081 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002082 err_code |= ERR_ALERT | ERR_FATAL;
2083 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002084 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01002085
2086 proto = protocol_by_family(sk->ss_family);
2087 if (!proto || !proto->connect) {
2088 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2089 file, linenum, args[0], args[1]);
2090 err_code |= ERR_ALERT | ERR_FATAL;
2091 goto out;
2092 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002093
2094 if (port1 != port2) {
2095 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2096 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002097 err_code |= ERR_ALERT | ERR_FATAL;
2098 goto out;
2099 }
2100
Willy Tarreau2aa38802013-02-20 19:20:59 +01002101 if (!port1) {
2102 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2103 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002104 err_code |= ERR_ALERT | ERR_FATAL;
2105 goto out;
2106 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002107
Emeric Brun32da3c42010-09-23 18:39:19 +02002108 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002109 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002110 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02002111 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02002112
Emeric Brun32da3c42010-09-23 18:39:19 +02002113 if (strcmp(newpeer->id, localpeer) == 0) {
2114 /* Current is local peer, it define a frontend */
2115 newpeer->local = 1;
Emeric Brunb3971ab2015-05-12 18:49:09 +02002116 peers->local = newpeer;
Emeric Brun32da3c42010-09-23 18:39:19 +02002117
2118 if (!curpeers->peers_fe) {
2119 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
2120 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2121 err_code |= ERR_ALERT | ERR_ABORT;
2122 goto out;
2123 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002124
Willy Tarreau237250c2011-07-29 01:49:03 +02002125 init_new_proxy(curpeers->peers_fe);
2126 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02002127 curpeers->peers_fe->id = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002128 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
2129 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau91d96282015-03-13 15:47:26 +01002130 peers_setup_frontend(curpeers->peers_fe);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002131
2132 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
2133
Willy Tarreau902636f2013-03-10 19:44:48 +01002134 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
2135 if (errmsg && *errmsg) {
2136 indent_msg(&errmsg, 2);
2137 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002138 }
2139 else
2140 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
2141 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002142 err_code |= ERR_FATAL;
2143 goto out;
2144 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02002145
2146 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01002147 l->maxaccept = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002148 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
2149 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
Willy Tarreau9903f0e2015-04-04 18:50:31 +02002150 l->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02002151 l->handler = process_stream;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002152 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01002153 l->default_target = ((struct proxy *)curpeers->peers_fe)->default_target;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002154 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
2155 global.maxsock += l->maxconn;
2156 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002157 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01002158 else {
2159 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
2160 file, linenum, args[0], args[1],
2161 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
2162 err_code |= ERR_FATAL;
2163 goto out;
2164 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002165 }
2166 } /* neither "peer" nor "peers" */
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002167 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
2168 curpeers->state = PR_STSTOPPED;
2169 }
2170 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
2171 curpeers->state = PR_STNEW;
2172 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002173 else if (*args[0] != 0) {
2174 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2175 err_code |= ERR_ALERT | ERR_FATAL;
2176 goto out;
2177 }
2178
2179out:
Willy Tarreau902636f2013-03-10 19:44:48 +01002180 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02002181 return err_code;
2182}
2183
Baptiste Assmann325137d2015-04-13 23:40:55 +02002184/*
2185 * Parse a <resolvers> section.
2186 * Returns the error code, 0 if OK, or any combination of :
2187 * - ERR_ABORT: must abort ASAP
2188 * - ERR_FATAL: we can continue parsing but not start the service
2189 * - ERR_WARN: a warning has been emitted
2190 * - ERR_ALERT: an alert has been emitted
2191 * Only the two first ones can stop processing, the two others are just
2192 * indicators.
2193 */
2194int cfg_parse_resolvers(const char *file, int linenum, char **args, int kwm)
2195{
2196 static struct dns_resolvers *curr_resolvers = NULL;
2197 struct dns_nameserver *newnameserver = NULL;
2198 const char *err;
2199 int err_code = 0;
2200 char *errmsg = NULL;
2201
2202 if (strcmp(args[0], "resolvers") == 0) { /* new resolvers section */
2203 if (!*args[1]) {
2204 Alert("parsing [%s:%d] : missing name for resolvers section.\n", file, linenum);
2205 err_code |= ERR_ALERT | ERR_ABORT;
2206 goto out;
2207 }
2208
2209 err = invalid_char(args[1]);
2210 if (err) {
2211 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2212 file, linenum, *err, args[0], args[1]);
2213 err_code |= ERR_ALERT | ERR_ABORT;
2214 goto out;
2215 }
2216
2217 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
2218 /* Error if two resolvers owns the same name */
2219 if (strcmp(curr_resolvers->id, args[1]) == 0) {
2220 Alert("Parsing [%s:%d]: resolvers '%s' has same name as another resolvers (declared at %s:%d).\n",
2221 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2222 err_code |= ERR_ALERT | ERR_ABORT;
2223 }
2224 }
2225
2226 if ((curr_resolvers = (struct dns_resolvers *)calloc(1, sizeof(struct dns_resolvers))) == NULL) {
2227 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2228 err_code |= ERR_ALERT | ERR_ABORT;
2229 goto out;
2230 }
2231
2232 /* default values */
2233 LIST_ADDQ(&dns_resolvers, &curr_resolvers->list);
2234 curr_resolvers->conf.file = strdup(file);
2235 curr_resolvers->conf.line = linenum;
2236 curr_resolvers->id = strdup(args[1]);
2237 curr_resolvers->query_ids = EB_ROOT;
2238 /* default hold period for valid is 10s */
Baptiste Assmann4c5490a2015-07-14 21:42:49 +02002239 curr_resolvers->hold.valid = 10000;
2240 curr_resolvers->timeout.retry = 1000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002241 curr_resolvers->resolve_retries = 3;
2242 LIST_INIT(&curr_resolvers->nameserver_list);
2243 LIST_INIT(&curr_resolvers->curr_resolution);
2244 }
2245 else if (strcmp(args[0], "nameserver") == 0) { /* nameserver definition */
2246 struct sockaddr_storage *sk;
2247 int port1, port2;
2248 struct protocol *proto;
2249
2250 if (!*args[2]) {
2251 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2252 file, linenum, args[0]);
2253 err_code |= ERR_ALERT | ERR_FATAL;
2254 goto out;
2255 }
2256
2257 err = invalid_char(args[1]);
2258 if (err) {
2259 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2260 file, linenum, *err, args[1]);
2261 err_code |= ERR_ALERT | ERR_FATAL;
2262 goto out;
2263 }
2264
Baptiste Assmanna315c552015-11-02 22:55:49 +01002265 list_for_each_entry(newnameserver, &curr_resolvers->nameserver_list, list) {
2266 /* Error if two resolvers owns the same name */
2267 if (strcmp(newnameserver->id, args[1]) == 0) {
2268 Alert("Parsing [%s:%d]: nameserver '%s' has same name as another nameserver (declared at %s:%d).\n",
2269 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2270 err_code |= ERR_ALERT | ERR_FATAL;
2271 }
2272 }
2273
Baptiste Assmann325137d2015-04-13 23:40:55 +02002274 if ((newnameserver = (struct dns_nameserver *)calloc(1, sizeof(struct dns_nameserver))) == NULL) {
2275 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2276 err_code |= ERR_ALERT | ERR_ABORT;
2277 goto out;
2278 }
2279
2280 /* the nameservers are linked backward first */
2281 LIST_ADDQ(&curr_resolvers->nameserver_list, &newnameserver->list);
2282 curr_resolvers->count_nameservers++;
2283 newnameserver->resolvers = curr_resolvers;
2284 newnameserver->conf.file = strdup(file);
2285 newnameserver->conf.line = linenum;
2286 newnameserver->id = strdup(args[1]);
2287
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002288 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002289 if (!sk) {
2290 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2291 err_code |= ERR_ALERT | ERR_FATAL;
2292 goto out;
2293 }
2294
2295 proto = protocol_by_family(sk->ss_family);
2296 if (!proto || !proto->connect) {
2297 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2298 file, linenum, args[0], args[1]);
2299 err_code |= ERR_ALERT | ERR_FATAL;
2300 goto out;
2301 }
2302
2303 if (port1 != port2) {
2304 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2305 file, linenum, args[0], args[1], args[2]);
2306 err_code |= ERR_ALERT | ERR_FATAL;
2307 goto out;
2308 }
2309
2310 newnameserver->addr = *sk;
2311 }
2312 else if (strcmp(args[0], "hold") == 0) { /* hold periods */
2313 const char *res;
2314 unsigned int time;
2315
2316 if (!*args[2]) {
2317 Alert("parsing [%s:%d] : '%s' expects an <event> and a <time> as arguments.\n",
2318 file, linenum, args[0]);
2319 Alert("<event> can be either 'valid', 'nx', 'refused', 'timeout', or 'other'\n");
2320 err_code |= ERR_ALERT | ERR_FATAL;
2321 goto out;
2322 }
2323 res = parse_time_err(args[2], &time, TIME_UNIT_MS);
2324 if (res) {
2325 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2326 file, linenum, *res, args[0]);
2327 err_code |= ERR_ALERT | ERR_FATAL;
2328 goto out;
2329 }
2330 if (strcmp(args[1], "valid") == 0)
2331 curr_resolvers->hold.valid = time;
2332 else {
2333 Alert("parsing [%s:%d] : '%s' unknown <event>: '%s', expects 'valid'\n",
2334 file, linenum, args[0], args[1]);
2335 err_code |= ERR_ALERT | ERR_FATAL;
2336 goto out;
2337 }
2338
2339 }
2340 else if (strcmp(args[0], "resolve_retries") == 0) {
2341 if (!*args[1]) {
2342 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2343 file, linenum, args[0]);
2344 err_code |= ERR_ALERT | ERR_FATAL;
2345 goto out;
2346 }
2347 curr_resolvers->resolve_retries = atoi(args[1]);
2348 }
2349 else if (strcmp(args[0], "timeout") == 0) {
2350 const char *res;
2351 unsigned int timeout_retry;
2352
2353 if (!*args[2]) {
2354 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments.\n",
2355 file, linenum, args[0]);
2356 err_code |= ERR_ALERT | ERR_FATAL;
2357 goto out;
2358 }
2359 res = parse_time_err(args[2], &timeout_retry, TIME_UNIT_MS);
2360 if (res) {
2361 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2362 file, linenum, *res, args[0]);
2363 err_code |= ERR_ALERT | ERR_FATAL;
2364 goto out;
2365 }
2366 curr_resolvers->timeout.retry = timeout_retry;
2367 } /* neither "nameserver" nor "resolvers" */
2368 else if (*args[0] != 0) {
2369 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2370 err_code |= ERR_ALERT | ERR_FATAL;
2371 goto out;
2372 }
2373
2374 out:
2375 free(errmsg);
2376 return err_code;
2377}
Simon Horman0d16a402015-01-30 11:22:58 +09002378
2379/*
William Lallemand51097192015-04-14 16:35:22 +02002380 * Parse a line in a <listen>, <frontend> or <backend> section.
Simon Horman0d16a402015-01-30 11:22:58 +09002381 * Returns the error code, 0 if OK, or any combination of :
2382 * - ERR_ABORT: must abort ASAP
2383 * - ERR_FATAL: we can continue parsing but not start the service
2384 * - ERR_WARN: a warning has been emitted
2385 * - ERR_ALERT: an alert has been emitted
2386 * Only the two first ones can stop processing, the two others are just
2387 * indicators.
2388 */
2389int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
2390{
2391 static struct mailers *curmailers = NULL;
2392 struct mailer *newmailer = NULL;
2393 const char *err;
2394 int err_code = 0;
2395 char *errmsg = NULL;
2396
2397 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
2398 if (!*args[1]) {
2399 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
2400 err_code |= ERR_ALERT | ERR_ABORT;
2401 goto out;
2402 }
2403
2404 err = invalid_char(args[1]);
2405 if (err) {
2406 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2407 file, linenum, *err, args[0], args[1]);
2408 err_code |= ERR_ALERT | ERR_ABORT;
2409 goto out;
2410 }
2411
2412 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
2413 /*
2414 * If there are two proxies with the same name only following
2415 * combinations are allowed:
2416 */
2417 if (strcmp(curmailers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002418 Alert("Parsing [%s:%d]: mailers section '%s' has the same name as another mailers section declared at %s:%d.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002419 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002420 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman0d16a402015-01-30 11:22:58 +09002421 }
2422 }
2423
2424 if ((curmailers = (struct mailers *)calloc(1, sizeof(struct mailers))) == NULL) {
2425 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2426 err_code |= ERR_ALERT | ERR_ABORT;
2427 goto out;
2428 }
2429
2430 curmailers->next = mailers;
2431 mailers = curmailers;
2432 curmailers->conf.file = strdup(file);
2433 curmailers->conf.line = linenum;
2434 curmailers->id = strdup(args[1]);
2435 }
2436 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
2437 struct sockaddr_storage *sk;
2438 int port1, port2;
2439 struct protocol *proto;
2440
2441 if (!*args[2]) {
2442 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2443 file, linenum, args[0]);
2444 err_code |= ERR_ALERT | ERR_FATAL;
2445 goto out;
2446 }
2447
2448 err = invalid_char(args[1]);
2449 if (err) {
2450 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2451 file, linenum, *err, args[1]);
2452 err_code |= ERR_ALERT | ERR_FATAL;
2453 goto out;
2454 }
2455
2456 if ((newmailer = (struct mailer *)calloc(1, sizeof(struct mailer))) == NULL) {
2457 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2458 err_code |= ERR_ALERT | ERR_ABORT;
2459 goto out;
2460 }
2461
2462 /* the mailers are linked backwards first */
2463 curmailers->count++;
2464 newmailer->next = curmailers->mailer_list;
2465 curmailers->mailer_list = newmailer;
2466 newmailer->mailers = curmailers;
2467 newmailer->conf.file = strdup(file);
2468 newmailer->conf.line = linenum;
2469
2470 newmailer->id = strdup(args[1]);
2471
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002472 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Simon Horman0d16a402015-01-30 11:22:58 +09002473 if (!sk) {
2474 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2475 err_code |= ERR_ALERT | ERR_FATAL;
2476 goto out;
2477 }
2478
2479 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002480 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2481 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002482 file, linenum, args[0], args[1]);
2483 err_code |= ERR_ALERT | ERR_FATAL;
2484 goto out;
2485 }
2486
2487 if (port1 != port2) {
2488 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2489 file, linenum, args[0], args[1], args[2]);
2490 err_code |= ERR_ALERT | ERR_FATAL;
2491 goto out;
2492 }
2493
2494 if (!port1) {
2495 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2496 file, linenum, args[0], args[1], args[2]);
2497 err_code |= ERR_ALERT | ERR_FATAL;
2498 goto out;
2499 }
2500
2501 newmailer->addr = *sk;
2502 newmailer->proto = proto;
2503 newmailer->xprt = &raw_sock;
2504 newmailer->sock_init_arg = NULL;
2505 } /* neither "mailer" nor "mailers" */
2506 else if (*args[0] != 0) {
2507 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2508 err_code |= ERR_ALERT | ERR_FATAL;
2509 goto out;
2510 }
2511
2512out:
2513 free(errmsg);
2514 return err_code;
2515}
2516
Simon Horman9dc49962015-01-30 11:22:59 +09002517static void free_email_alert(struct proxy *p)
2518{
2519 free(p->email_alert.mailers.name);
2520 p->email_alert.mailers.name = NULL;
2521 free(p->email_alert.from);
2522 p->email_alert.from = NULL;
2523 free(p->email_alert.to);
2524 p->email_alert.to = NULL;
2525 free(p->email_alert.myhostname);
2526 p->email_alert.myhostname = NULL;
2527}
2528
Willy Tarreau3842f002009-06-14 11:39:52 +02002529int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002530{
2531 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002532 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002533 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002534 int rc;
2535 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002536 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002537 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002538 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002539 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002540 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002541
Willy Tarreau977b8e42006-12-29 14:19:17 +01002542 if (!strcmp(args[0], "listen"))
2543 rc = PR_CAP_LISTEN;
2544 else if (!strcmp(args[0], "frontend"))
2545 rc = PR_CAP_FE | PR_CAP_RS;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02002546 else if (!strcmp(args[0], "backend"))
Willy Tarreau977b8e42006-12-29 14:19:17 +01002547 rc = PR_CAP_BE | PR_CAP_RS;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002548 else
2549 rc = PR_CAP_NONE;
2550
2551 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002552 if (!*args[1]) {
2553 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
2554 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
2555 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002556 err_code |= ERR_ALERT | ERR_ABORT;
2557 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002558 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002559
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002560 err = invalid_char(args[1]);
2561 if (err) {
2562 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2563 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002564 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002565 }
2566
Willy Tarreau8f50b682015-05-26 11:45:02 +02002567 curproxy = (rc & PR_CAP_FE) ? proxy_fe_by_name(args[1]) : proxy_be_by_name(args[1]);
2568 if (curproxy) {
2569 Alert("Parsing [%s:%d]: %s '%s' has the same name as %s '%s' declared at %s:%d.\n",
2570 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2571 curproxy->id, curproxy->conf.file, curproxy->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002572 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002573 }
2574
Willy Tarreaubaaee002006-06-26 02:48:02 +02002575 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
2576 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002577 err_code |= ERR_ALERT | ERR_ABORT;
2578 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002579 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002580
Willy Tarreau97cb7802010-01-03 20:23:58 +01002581 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002582 curproxy->next = proxy;
2583 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002584 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2585 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002586 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002587 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002588 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002589 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002590
William Lallemand6e62fb62015-04-28 16:55:23 +02002591 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2592 if (curproxy->cap & PR_CAP_FE)
2593 Alert("parsing [%s:%d] : please use the 'bind' keyword for listening addresses.\n", file, linenum);
2594 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002595 }
2596
2597 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002598 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002599 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002600
Willy Tarreaubaaee002006-06-26 02:48:02 +02002601 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002602 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002603 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002604 curproxy->no_options = defproxy.no_options;
2605 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002606 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002607 curproxy->except_net = defproxy.except_net;
2608 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002609 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002610 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002611
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002612 if (defproxy.fwdfor_hdr_len) {
2613 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2614 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2615 }
2616
Willy Tarreaub86db342009-11-30 11:50:16 +01002617 if (defproxy.orgto_hdr_len) {
2618 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2619 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2620 }
2621
Mark Lamourinec2247f02012-01-04 13:02:01 -05002622 if (defproxy.server_id_hdr_len) {
2623 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2624 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2625 }
2626
Willy Tarreau977b8e42006-12-29 14:19:17 +01002627 if (curproxy->cap & PR_CAP_FE) {
2628 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002629 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002630 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002631
2632 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002633 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2634 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002635
2636 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2637 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002638
Willy Tarreau977b8e42006-12-29 14:19:17 +01002639 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002640 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002641 curproxy->fullconn = defproxy.fullconn;
2642 curproxy->conn_retries = defproxy.conn_retries;
Joseph Lynch726ab712015-05-11 23:25:34 -07002643 curproxy->redispatch_after = defproxy.redispatch_after;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002644 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002645
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002646 if (defproxy.check_req) {
2647 curproxy->check_req = calloc(1, defproxy.check_len);
2648 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2649 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002650 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002651
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002652 if (defproxy.expect_str) {
2653 curproxy->expect_str = strdup(defproxy.expect_str);
2654 if (defproxy.expect_regex) {
2655 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002656 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2657 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002658 }
2659 }
2660
Willy Tarreau67402132012-05-31 20:40:20 +02002661 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002662 if (defproxy.cookie_name)
2663 curproxy->cookie_name = strdup(defproxy.cookie_name);
2664 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002665 if (defproxy.cookie_domain)
2666 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002667
Willy Tarreau31936852010-10-06 16:59:56 +02002668 if (defproxy.cookie_maxidle)
2669 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2670
2671 if (defproxy.cookie_maxlife)
2672 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2673
Emeric Brun647caf12009-06-30 17:57:00 +02002674 if (defproxy.rdp_cookie_name)
2675 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2676 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2677
Willy Tarreau01732802007-11-01 22:48:15 +01002678 if (defproxy.url_param_name)
2679 curproxy->url_param_name = strdup(defproxy.url_param_name);
2680 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002681
Benoitaffb4812009-03-25 13:02:10 +01002682 if (defproxy.hh_name)
2683 curproxy->hh_name = strdup(defproxy.hh_name);
2684 curproxy->hh_len = defproxy.hh_len;
2685 curproxy->hh_match_domain = defproxy.hh_match_domain;
2686
Willy Tarreauef9a3602012-12-08 22:29:20 +01002687 if (defproxy.conn_src.iface_name)
2688 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2689 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002690 curproxy->conn_src.opts = defproxy.conn_src.opts;
Willy Tarreau29fbe512015-08-20 19:35:14 +02002691#if defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002692 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002693#endif
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02002694 curproxy->load_server_state_from_file = defproxy.load_server_state_from_file;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002695 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002696
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002697 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002698 if (defproxy.capture_name)
2699 curproxy->capture_name = strdup(defproxy.capture_name);
2700 curproxy->capture_namelen = defproxy.capture_namelen;
2701 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002702 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002703
Willy Tarreau977b8e42006-12-29 14:19:17 +01002704 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002705 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002706 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002707 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002708 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002709 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002710 curproxy->mon_net = defproxy.mon_net;
2711 curproxy->mon_mask = defproxy.mon_mask;
2712 if (defproxy.monitor_uri)
2713 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2714 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002715 if (defproxy.defbe.name)
2716 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002717
2718 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002719 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2720 if (curproxy->conf.logformat_string &&
2721 curproxy->conf.logformat_string != default_http_log_format &&
2722 curproxy->conf.logformat_string != default_tcp_log_format &&
2723 curproxy->conf.logformat_string != clf_http_log_format)
2724 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2725
2726 if (defproxy.conf.lfs_file) {
2727 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2728 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2729 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002730
2731 /* get either a pointer to the logformat string for RFC5424 structured-data or a copy of it */
2732 curproxy->conf.logformat_sd_string = defproxy.conf.logformat_sd_string;
2733 if (curproxy->conf.logformat_sd_string &&
2734 curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
2735 curproxy->conf.logformat_sd_string = strdup(curproxy->conf.logformat_sd_string);
2736
2737 if (defproxy.conf.lfsd_file) {
2738 curproxy->conf.lfsd_file = strdup(defproxy.conf.lfsd_file);
2739 curproxy->conf.lfsd_line = defproxy.conf.lfsd_line;
2740 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002741 }
2742
2743 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002744 curproxy->timeout.connect = defproxy.timeout.connect;
2745 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002746 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002747 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002748 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002749 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002750 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002751 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002752 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002753 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002754 }
2755
Willy Tarreaubaaee002006-06-26 02:48:02 +02002756 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002757 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002758
2759 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002760 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002761 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002762 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002763 LIST_INIT(&node->list);
2764 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2765 }
2766
Willy Tarreau62a61232013-04-12 18:13:46 +02002767 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2768 if (curproxy->conf.uniqueid_format_string)
2769 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2770
Dragan Dosen43885c72015-10-01 13:18:13 +02002771 chunk_dup(&curproxy->log_tag, &defproxy.log_tag);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002772
Willy Tarreau62a61232013-04-12 18:13:46 +02002773 if (defproxy.conf.uif_file) {
2774 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2775 curproxy->conf.uif_line = defproxy.conf.uif_line;
2776 }
William Lallemanda73203e2012-03-12 12:48:57 +01002777
2778 /* copy default header unique id */
2779 if (defproxy.header_unique_id)
2780 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2781
William Lallemand82fe75c2012-10-23 10:25:10 +02002782 /* default compression options */
2783 if (defproxy.comp != NULL) {
2784 curproxy->comp = calloc(1, sizeof(struct comp));
2785 curproxy->comp->algos = defproxy.comp->algos;
2786 curproxy->comp->types = defproxy.comp->types;
2787 }
2788
Willy Tarreaubaaee002006-06-26 02:48:02 +02002789 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002790 curproxy->conf.used_listener_id = EB_ROOT;
2791 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002792
Simon Horman98637e52014-06-20 12:30:16 +09002793 if (defproxy.check_path)
2794 curproxy->check_path = strdup(defproxy.check_path);
2795 if (defproxy.check_command)
2796 curproxy->check_command = strdup(defproxy.check_command);
2797
Simon Horman9dc49962015-01-30 11:22:59 +09002798 if (defproxy.email_alert.mailers.name)
2799 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2800 if (defproxy.email_alert.from)
2801 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2802 if (defproxy.email_alert.to)
2803 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2804 if (defproxy.email_alert.myhostname)
2805 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09002806 curproxy->email_alert.level = defproxy.email_alert.level;
Cyril Bonté7e084702015-12-04 03:07:06 +01002807 curproxy->email_alert.set = defproxy.email_alert.set;
Simon Horman9dc49962015-01-30 11:22:59 +09002808
Willy Tarreau93893792009-07-23 13:19:11 +02002809 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002810 }
2811 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2812 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002813 /* FIXME-20070101: we should do this too at the end of the
2814 * config parsing to free all default values.
2815 */
William Lallemand6e62fb62015-04-28 16:55:23 +02002816 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2817 err_code |= ERR_ABORT;
2818 goto out;
2819 }
2820
Willy Tarreaua534fea2008-08-03 12:19:50 +02002821 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002822 free(defproxy.check_command);
2823 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002824 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002825 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002826 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002827 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002828 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002829 free(defproxy.capture_name);
2830 free(defproxy.monitor_uri);
2831 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002832 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002833 free(defproxy.fwdfor_hdr_name);
2834 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002835 free(defproxy.orgto_hdr_name);
2836 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002837 free(defproxy.server_id_hdr_name);
2838 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002839 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002840 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002841 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002842 free(defproxy.expect_regex);
2843 defproxy.expect_regex = NULL;
2844 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002845
Willy Tarreau62a61232013-04-12 18:13:46 +02002846 if (defproxy.conf.logformat_string != default_http_log_format &&
2847 defproxy.conf.logformat_string != default_tcp_log_format &&
2848 defproxy.conf.logformat_string != clf_http_log_format)
2849 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002850
Willy Tarreau62a61232013-04-12 18:13:46 +02002851 free(defproxy.conf.uniqueid_format_string);
2852 free(defproxy.conf.lfs_file);
2853 free(defproxy.conf.uif_file);
Dragan Dosen43885c72015-10-01 13:18:13 +02002854 chunk_destroy(&defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09002855 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02002856
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002857 if (defproxy.conf.logformat_sd_string != default_rfc5424_sd_log_format)
2858 free(defproxy.conf.logformat_sd_string);
2859 free(defproxy.conf.lfsd_file);
2860
Willy Tarreaua534fea2008-08-03 12:19:50 +02002861 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002862 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002863
Willy Tarreaubaaee002006-06-26 02:48:02 +02002864 /* we cannot free uri_auth because it might already be used */
2865 init_default_instance();
2866 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002867 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2868 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002869 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002870 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002871 }
2872 else if (curproxy == NULL) {
2873 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002874 err_code |= ERR_ALERT | ERR_FATAL;
2875 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002876 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002877
2878 /* update the current file and line being parsed */
2879 curproxy->conf.args.file = curproxy->conf.file;
2880 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002881
2882 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002883 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2884 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2885 if (err_code & ERR_FATAL)
2886 goto out;
2887 }
2888 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002889 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002890 int cur_arg;
2891
Willy Tarreaubaaee002006-06-26 02:48:02 +02002892 if (curproxy == &defproxy) {
2893 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002894 err_code |= ERR_ALERT | ERR_FATAL;
2895 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002896 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002897 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002898 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002899
Willy Tarreau24709282013-03-10 21:32:12 +01002900 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002901 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002902 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002903 err_code |= ERR_ALERT | ERR_FATAL;
2904 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002905 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002906
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002907 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002908
2909 /* use default settings for unix sockets */
2910 bind_conf->ux.uid = global.unix_bind.ux.uid;
2911 bind_conf->ux.gid = global.unix_bind.ux.gid;
2912 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002913
2914 /* NOTE: the following line might create several listeners if there
2915 * are comma-separated IPs or port ranges. So all further processing
2916 * will have to be applied to all listeners created after last_listen.
2917 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002918 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2919 if (errmsg && *errmsg) {
2920 indent_msg(&errmsg, 2);
2921 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002922 }
2923 else
2924 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2925 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002926 err_code |= ERR_ALERT | ERR_FATAL;
2927 goto out;
2928 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002929
Willy Tarreau4348fad2012-09-20 16:48:07 +02002930 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2931 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002932 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002933 }
2934
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002935 cur_arg = 2;
2936 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002937 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002938 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002939 char *err;
2940
Willy Tarreau26982662012-09-12 23:17:10 +02002941 kw = bind_find_kw(args[cur_arg]);
2942 if (kw) {
2943 char *err = NULL;
2944 int code;
2945
2946 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002947 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2948 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002949 cur_arg += 1 + kw->skip ;
2950 err_code |= ERR_ALERT | ERR_FATAL;
2951 goto out;
2952 }
2953
Willy Tarreau4348fad2012-09-20 16:48:07 +02002954 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002955 err_code |= code;
2956
2957 if (code) {
2958 if (err && *err) {
2959 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002960 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002961 }
2962 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002963 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2964 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002965 if (code & ERR_FATAL) {
2966 free(err);
2967 cur_arg += 1 + kw->skip;
2968 goto out;
2969 }
2970 }
2971 free(err);
2972 cur_arg += 1 + kw->skip;
2973 continue;
2974 }
2975
Willy Tarreau8638f482012-09-18 18:01:17 +02002976 err = NULL;
2977 if (!bind_dumped) {
2978 bind_dump_kws(&err);
2979 indent_msg(&err, 4);
2980 bind_dumped = 1;
2981 }
2982
2983 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2984 file, linenum, args[0], args[1], args[cur_arg],
2985 err ? " Registered keywords :" : "", err ? err : "");
2986 free(err);
2987
Willy Tarreau93893792009-07-23 13:19:11 +02002988 err_code |= ERR_ALERT | ERR_FATAL;
2989 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002990 }
Willy Tarreau93893792009-07-23 13:19:11 +02002991 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002992 }
2993 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002994 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002995 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2996 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002997 err_code |= ERR_ALERT | ERR_FATAL;
2998 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002999 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003000 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003001 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003002
Willy Tarreaubaaee002006-06-26 02:48:02 +02003003 /* flush useless bits */
3004 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02003005 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003006 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02003007 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003008 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003009 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003010
William Lallemanddf1425a2015-04-28 20:17:49 +02003011 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3012 goto out;
3013
Willy Tarreau1c47f852006-07-09 08:22:27 +02003014 if (!*args[1]) {
3015 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
3016 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003017 err_code |= ERR_ALERT | ERR_FATAL;
3018 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003019 }
3020
Willy Tarreaua534fea2008-08-03 12:19:50 +02003021 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003022 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02003023 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003024 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02003025 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
3026
Willy Tarreau93893792009-07-23 13:19:11 +02003027 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003028 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003029 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
William Lallemanddf1425a2015-04-28 20:17:49 +02003030 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3031 goto out;
3032
Willy Tarreaubaaee002006-06-26 02:48:02 +02003033 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
3034 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
3035 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
3036 else {
3037 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003038 err_code |= ERR_ALERT | ERR_FATAL;
3039 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003040 }
3041 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003042 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003043 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003044
3045 if (curproxy == &defproxy) {
3046 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3047 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003048 err_code |= ERR_ALERT | ERR_FATAL;
3049 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003050 }
3051
William Lallemanddf1425a2015-04-28 20:17:49 +02003052 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3053 goto out;
3054
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003055 if (!*args[1]) {
3056 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3057 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003058 err_code |= ERR_ALERT | ERR_FATAL;
3059 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003060 }
3061
3062 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003063 curproxy->conf.id.key = curproxy->uuid;
Willy Tarreau0d1fdf72015-05-27 16:44:02 +02003064 curproxy->options |= PR_O_FORCED_ID;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003065
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003066 if (curproxy->uuid <= 0) {
3067 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003068 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003069 err_code |= ERR_ALERT | ERR_FATAL;
3070 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003071 }
3072
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003073 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
3074 if (node) {
3075 struct proxy *target = container_of(node, struct proxy, conf.id);
3076 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
3077 file, linenum, proxy_type_str(curproxy), curproxy->id,
3078 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
3079 err_code |= ERR_ALERT | ERR_FATAL;
3080 goto out;
3081 }
3082 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003083 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003084 else if (!strcmp(args[0], "description")) {
3085 int i, len=0;
3086 char *d;
3087
Cyril Bonté99ed3272010-01-24 23:29:44 +01003088 if (curproxy == &defproxy) {
3089 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3090 file, linenum, args[0]);
3091 err_code |= ERR_ALERT | ERR_FATAL;
3092 goto out;
3093 }
3094
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003095 if (!*args[1]) {
3096 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
3097 file, linenum, args[0]);
3098 return -1;
3099 }
3100
Willy Tarreau348acfe2014-04-14 15:00:39 +02003101 for (i = 1; *args[i]; i++)
3102 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003103
3104 d = (char *)calloc(1, len);
3105 curproxy->desc = d;
3106
Willy Tarreau348acfe2014-04-14 15:00:39 +02003107 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
3108 for (i = 2; *args[i]; i++)
3109 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003110
3111 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003112 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
William Lallemanddf1425a2015-04-28 20:17:49 +02003113 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3114 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003115 curproxy->state = PR_STSTOPPED;
3116 }
3117 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
William Lallemanddf1425a2015-04-28 20:17:49 +02003118 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3119 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003120 curproxy->state = PR_STNEW;
3121 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003122 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
3123 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003124 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003125
3126 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003127 unsigned int low, high;
3128
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003129 if (strcmp(args[cur_arg], "all") == 0) {
3130 set = 0;
3131 break;
3132 }
3133 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003134 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003135 }
3136 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003137 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003138 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01003139 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003140 char *dash = strchr(args[cur_arg], '-');
3141
3142 low = high = str2uic(args[cur_arg]);
3143 if (dash)
3144 high = str2uic(dash + 1);
3145
3146 if (high < low) {
3147 unsigned int swap = low;
3148 low = high;
3149 high = swap;
3150 }
3151
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003152 if (low < 1 || high > LONGBITS) {
3153 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
3154 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02003155 err_code |= ERR_ALERT | ERR_FATAL;
3156 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003157 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01003158 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003159 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003160 }
3161 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003162 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
3163 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003164 err_code |= ERR_ALERT | ERR_FATAL;
3165 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003166 }
3167 cur_arg++;
3168 }
3169 curproxy->bind_proc = set;
3170 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003171 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02003172 if (curproxy == &defproxy) {
3173 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003174 err_code |= ERR_ALERT | ERR_FATAL;
3175 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003176 }
3177
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003178 err = invalid_char(args[1]);
3179 if (err) {
3180 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
3181 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003182 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003183 }
3184
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01003185 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003186 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
3187 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003188 err_code |= ERR_ALERT | ERR_FATAL;
3189 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003190 }
3191 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003192 else if (!strcmp(args[0], "cookie")) { /* cookie name */
3193 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003194
Willy Tarreau977b8e42006-12-29 14:19:17 +01003195 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003196 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003197
Willy Tarreaubaaee002006-06-26 02:48:02 +02003198 if (*(args[1]) == 0) {
3199 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
3200 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003201 err_code |= ERR_ALERT | ERR_FATAL;
3202 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003203 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003204
Willy Tarreau67402132012-05-31 20:40:20 +02003205 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003206 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01003207 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003208 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003209 curproxy->cookie_name = strdup(args[1]);
3210 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003211
Willy Tarreaubaaee002006-06-26 02:48:02 +02003212 cur_arg = 2;
3213 while (*(args[cur_arg])) {
3214 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003215 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003216 }
3217 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003218 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003219 }
3220 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003221 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003222 }
3223 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003224 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003225 }
3226 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003227 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003228 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003229 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003230 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003231 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003232 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003233 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003234 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02003235 else if (!strcmp(args[cur_arg], "httponly")) {
3236 curproxy->ck_opts |= PR_CK_HTTPONLY;
3237 }
3238 else if (!strcmp(args[cur_arg], "secure")) {
3239 curproxy->ck_opts |= PR_CK_SECURE;
3240 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003241 else if (!strcmp(args[cur_arg], "domain")) {
3242 if (!*args[cur_arg + 1]) {
3243 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
3244 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003245 err_code |= ERR_ALERT | ERR_FATAL;
3246 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003247 }
3248
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003249 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003250 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003251 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
3252 " dots nor does not start with a dot."
3253 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003254 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003255 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003256 }
3257
3258 err = invalid_domainchar(args[cur_arg + 1]);
3259 if (err) {
3260 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
3261 file, linenum, *err, args[cur_arg + 1]);
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
Willy Tarreau68a897b2009-12-03 23:28:34 +01003266 if (!curproxy->cookie_domain) {
3267 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
3268 } else {
3269 /* one domain was already specified, add another one by
3270 * building the string which will be returned along with
3271 * the cookie.
3272 */
3273 char *new_ptr;
3274 int new_len = strlen(curproxy->cookie_domain) +
3275 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
3276 new_ptr = malloc(new_len);
3277 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
3278 free(curproxy->cookie_domain);
3279 curproxy->cookie_domain = new_ptr;
3280 }
Willy Tarreau31936852010-10-06 16:59:56 +02003281 cur_arg++;
3282 }
3283 else if (!strcmp(args[cur_arg], "maxidle")) {
3284 unsigned int maxidle;
3285 const char *res;
3286
3287 if (!*args[cur_arg + 1]) {
3288 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
3289 file, linenum, args[cur_arg]);
3290 err_code |= ERR_ALERT | ERR_FATAL;
3291 goto out;
3292 }
3293
3294 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
3295 if (res) {
3296 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3297 file, linenum, *res, args[cur_arg]);
3298 err_code |= ERR_ALERT | ERR_FATAL;
3299 goto out;
3300 }
3301 curproxy->cookie_maxidle = maxidle;
3302 cur_arg++;
3303 }
3304 else if (!strcmp(args[cur_arg], "maxlife")) {
3305 unsigned int maxlife;
3306 const char *res;
3307
3308 if (!*args[cur_arg + 1]) {
3309 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
3310 file, linenum, args[cur_arg]);
3311 err_code |= ERR_ALERT | ERR_FATAL;
3312 goto out;
3313 }
3314
3315 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
3316 if (res) {
3317 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3318 file, linenum, *res, args[cur_arg]);
3319 err_code |= ERR_ALERT | ERR_FATAL;
3320 goto out;
3321 }
3322 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003323 cur_arg++;
3324 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003325 else {
Willy Tarreau31936852010-10-06 16:59:56 +02003326 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 +02003327 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003328 err_code |= ERR_ALERT | ERR_FATAL;
3329 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003330 }
3331 cur_arg++;
3332 }
Willy Tarreau67402132012-05-31 20:40:20 +02003333 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003334 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
3335 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003336 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003337 }
3338
Willy Tarreau67402132012-05-31 20:40:20 +02003339 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003340 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
3341 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003342 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003343 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003344
Willy Tarreau67402132012-05-31 20:40:20 +02003345 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003346 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
3347 file, linenum);
3348 err_code |= ERR_ALERT | ERR_FATAL;
3349 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003350 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09003351 else if (!strcmp(args[0], "email-alert")) {
3352 if (*(args[1]) == 0) {
3353 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3354 file, linenum, args[0]);
3355 err_code |= ERR_ALERT | ERR_FATAL;
3356 goto out;
3357 }
3358
3359 if (!strcmp(args[1], "from")) {
3360 if (*(args[1]) == 0) {
3361 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3362 file, linenum, args[1]);
3363 err_code |= ERR_ALERT | ERR_FATAL;
3364 goto out;
3365 }
3366 free(curproxy->email_alert.from);
3367 curproxy->email_alert.from = strdup(args[2]);
3368 }
3369 else if (!strcmp(args[1], "mailers")) {
3370 if (*(args[1]) == 0) {
3371 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3372 file, linenum, args[1]);
3373 err_code |= ERR_ALERT | ERR_FATAL;
3374 goto out;
3375 }
3376 free(curproxy->email_alert.mailers.name);
3377 curproxy->email_alert.mailers.name = strdup(args[2]);
3378 }
3379 else if (!strcmp(args[1], "myhostname")) {
3380 if (*(args[1]) == 0) {
3381 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3382 file, linenum, args[1]);
3383 err_code |= ERR_ALERT | ERR_FATAL;
3384 goto out;
3385 }
3386 free(curproxy->email_alert.myhostname);
3387 curproxy->email_alert.myhostname = strdup(args[2]);
3388 }
Simon Horman64e34162015-02-06 11:11:57 +09003389 else if (!strcmp(args[1], "level")) {
3390 curproxy->email_alert.level = get_log_level(args[2]);
3391 if (curproxy->email_alert.level < 0) {
3392 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
3393 file, linenum, args[1], args[2]);
3394 err_code |= ERR_ALERT | ERR_FATAL;
3395 goto out;
3396 }
3397 }
Simon Horman9dc49962015-01-30 11:22:59 +09003398 else if (!strcmp(args[1], "to")) {
3399 if (*(args[1]) == 0) {
3400 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3401 file, linenum, args[1]);
3402 err_code |= ERR_ALERT | ERR_FATAL;
3403 goto out;
3404 }
3405 free(curproxy->email_alert.to);
3406 curproxy->email_alert.to = strdup(args[2]);
3407 }
3408 else {
3409 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
3410 file, linenum, args[1]);
3411 err_code |= ERR_ALERT | ERR_FATAL;
3412 goto out;
3413 }
Simon Horman64e34162015-02-06 11:11:57 +09003414 /* Indicate that the email_alert is at least partially configured */
3415 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09003416 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09003417 else if (!strcmp(args[0], "external-check")) {
3418 if (*(args[1]) == 0) {
3419 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3420 file, linenum, args[0]);
3421 err_code |= ERR_ALERT | ERR_FATAL;
3422 goto out;
3423 }
3424
3425 if (!strcmp(args[1], "command")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003426 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003427 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003428 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003429 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3430 file, linenum, args[1]);
3431 err_code |= ERR_ALERT | ERR_FATAL;
3432 goto out;
3433 }
3434 free(curproxy->check_command);
3435 curproxy->check_command = strdup(args[2]);
3436 }
3437 else if (!strcmp(args[1], "path")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003438 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003439 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003440 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003441 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3442 file, linenum, args[1]);
3443 err_code |= ERR_ALERT | ERR_FATAL;
3444 goto out;
3445 }
3446 free(curproxy->check_path);
3447 curproxy->check_path = strdup(args[2]);
3448 }
3449 else {
3450 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
3451 file, linenum, args[1]);
3452 err_code |= ERR_ALERT | ERR_FATAL;
3453 goto out;
3454 }
3455 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02003456 else if (!strcmp(args[0], "persist")) { /* persist */
3457 if (*(args[1]) == 0) {
3458 Alert("parsing [%s:%d] : missing persist method.\n",
3459 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003460 err_code |= ERR_ALERT | ERR_FATAL;
3461 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003462 }
3463
3464 if (!strncmp(args[1], "rdp-cookie", 10)) {
3465 curproxy->options2 |= PR_O2_RDPC_PRST;
3466
Emeric Brunb982a3d2010-01-04 15:45:53 +01003467 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003468 const char *beg, *end;
3469
3470 beg = args[1] + 11;
3471 end = strchr(beg, ')');
3472
William Lallemanddf1425a2015-04-28 20:17:49 +02003473 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3474 goto out;
3475
Emeric Brun647caf12009-06-30 17:57:00 +02003476 if (!end || end == beg) {
3477 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3478 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003479 err_code |= ERR_ALERT | ERR_FATAL;
3480 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003481 }
3482
3483 free(curproxy->rdp_cookie_name);
3484 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3485 curproxy->rdp_cookie_len = end-beg;
3486 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003487 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003488 free(curproxy->rdp_cookie_name);
3489 curproxy->rdp_cookie_name = strdup("msts");
3490 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3491 }
3492 else { /* syntax */
3493 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3494 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003495 err_code |= ERR_ALERT | ERR_FATAL;
3496 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003497 }
3498 }
3499 else {
3500 Alert("parsing [%s:%d] : unknown persist method.\n",
3501 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003502 err_code |= ERR_ALERT | ERR_FATAL;
3503 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003504 }
3505 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003506 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreau6db62c52015-08-10 19:04:29 +02003507 Alert("parsing [%s:%d] : '%s' is not supported anymore, please check the documentation.\n", file, linenum, args[0]);
3508 err_code |= ERR_ALERT | ERR_FATAL;
3509 goto out;
3510 }
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02003511 else if (!strcmp(args[0], "load-server-state-from-file")) {
3512 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3513 err_code |= ERR_WARN;
3514 if (!strcmp(args[1], "global")) { /* use the file pointed to by global server-state-file directive */
3515 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_GLOBAL;
3516 }
3517 else if (!strcmp(args[1], "local")) { /* use the server-state-file-name variable to locate the server-state file */
3518 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_LOCAL;
3519 }
3520 else if (!strcmp(args[1], "none")) { /* don't use server-state-file directive for this backend */
3521 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
3522 }
3523 else {
3524 Alert("parsing [%s:%d] : '%s' expects 'global', 'local' or 'none'. Got '%s'\n",
3525 file, linenum, args[0], args[1]);
3526 err_code |= ERR_ALERT | ERR_FATAL;
3527 goto out;
3528 }
3529 }
3530 else if (!strcmp(args[0], "server-state-file-name")) {
3531 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3532 err_code |= ERR_WARN;
3533 if (*(args[1]) == 0) {
3534 Alert("parsing [%s:%d] : '%s' expects 'use-backend-name' or a string. Got no argument\n",
3535 file, linenum, args[0]);
3536 err_code |= ERR_ALERT | ERR_FATAL;
3537 goto out;
3538 }
3539 else if (!strcmp(args[1], "use-backend-name"))
3540 curproxy->server_state_file_name = strdup(curproxy->id);
3541 else
3542 curproxy->server_state_file_name = strdup(args[1]);
3543 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003544 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003545 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003546 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003547
Willy Tarreaubaaee002006-06-26 02:48:02 +02003548 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003549 if (curproxy == &defproxy) {
3550 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3551 err_code |= ERR_ALERT | ERR_FATAL;
3552 goto out;
3553 }
3554
William Lallemand1a748ae2015-05-19 16:37:23 +02003555 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3556 goto out;
3557
Willy Tarreaubaaee002006-06-26 02:48:02 +02003558 if (*(args[4]) == 0) {
3559 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3560 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003561 err_code |= ERR_ALERT | ERR_FATAL;
3562 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003563 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003564 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003565 curproxy->capture_name = strdup(args[2]);
3566 curproxy->capture_namelen = strlen(curproxy->capture_name);
3567 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003568 curproxy->to_log |= LW_COOKIE;
3569 }
3570 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3571 struct cap_hdr *hdr;
3572
3573 if (curproxy == &defproxy) {
3574 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 +02003575 err_code |= ERR_ALERT | ERR_FATAL;
3576 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003577 }
3578
William Lallemand1a748ae2015-05-19 16:37:23 +02003579 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3580 goto out;
3581
Willy Tarreaubaaee002006-06-26 02:48:02 +02003582 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3583 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3584 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003585 err_code |= ERR_ALERT | ERR_FATAL;
3586 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003587 }
3588
3589 hdr = calloc(sizeof(struct cap_hdr), 1);
3590 hdr->next = curproxy->req_cap;
3591 hdr->name = strdup(args[3]);
3592 hdr->namelen = strlen(args[3]);
3593 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003594 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003595 hdr->index = curproxy->nb_req_cap++;
3596 curproxy->req_cap = hdr;
3597 curproxy->to_log |= LW_REQHDR;
3598 }
3599 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3600 struct cap_hdr *hdr;
3601
3602 if (curproxy == &defproxy) {
3603 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 +02003604 err_code |= ERR_ALERT | ERR_FATAL;
3605 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003606 }
3607
William Lallemand1a748ae2015-05-19 16:37:23 +02003608 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3609 goto out;
3610
Willy Tarreaubaaee002006-06-26 02:48:02 +02003611 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3612 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3613 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003614 err_code |= ERR_ALERT | ERR_FATAL;
3615 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003616 }
3617 hdr = calloc(sizeof(struct cap_hdr), 1);
3618 hdr->next = curproxy->rsp_cap;
3619 hdr->name = strdup(args[3]);
3620 hdr->namelen = strlen(args[3]);
3621 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003622 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003623 hdr->index = curproxy->nb_rsp_cap++;
3624 curproxy->rsp_cap = hdr;
3625 curproxy->to_log |= LW_RSPHDR;
3626 }
3627 else {
3628 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3629 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003630 err_code |= ERR_ALERT | ERR_FATAL;
3631 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003632 }
3633 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003634 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003635 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003636 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003637
William Lallemanddf1425a2015-04-28 20:17:49 +02003638 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3639 goto out;
3640
Willy Tarreaubaaee002006-06-26 02:48:02 +02003641 if (*(args[1]) == 0) {
3642 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3643 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003644 err_code |= ERR_ALERT | ERR_FATAL;
3645 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003646 }
3647 curproxy->conn_retries = atol(args[1]);
3648 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003649 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003650 struct act_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003651
3652 if (curproxy == &defproxy) {
3653 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3654 err_code |= ERR_ALERT | ERR_FATAL;
3655 goto out;
3656 }
3657
Willy Tarreau20b0de52012-12-24 15:45:22 +01003658 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003659 !LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003660 (LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3661 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_DENY ||
3662 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REDIR ||
3663 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REQ_AUTH)) {
Willy Tarreau20b0de52012-12-24 15:45:22 +01003664 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 +01003665 file, linenum, args[0]);
3666 err_code |= ERR_WARN;
3667 }
3668
Willy Tarreauff011f22011-01-06 17:51:27 +01003669 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003670
Willy Tarreauff011f22011-01-06 17:51:27 +01003671 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003672 err_code |= ERR_ALERT | ERR_ABORT;
3673 goto out;
3674 }
3675
Willy Tarreau5002f572014-04-23 01:32:02 +02003676 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003677 err_code |= warnif_cond_conflicts(rule->cond,
3678 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3679 file, linenum);
3680
Willy Tarreauff011f22011-01-06 17:51:27 +01003681 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003682 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003683 else if (!strcmp(args[0], "http-response")) { /* response access control */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003684 struct act_rule *rule;
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003685
3686 if (curproxy == &defproxy) {
3687 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3688 err_code |= ERR_ALERT | ERR_FATAL;
3689 goto out;
3690 }
3691
3692 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003693 !LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003694 (LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3695 LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_DENY)) {
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003696 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3697 file, linenum, args[0]);
3698 err_code |= ERR_WARN;
3699 }
3700
3701 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3702
3703 if (!rule) {
3704 err_code |= ERR_ALERT | ERR_ABORT;
3705 goto out;
3706 }
3707
3708 err_code |= warnif_cond_conflicts(rule->cond,
3709 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3710 file, linenum);
3711
3712 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3713 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003714 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3715 /* set the header name and length into the proxy structure */
3716 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3717 err_code |= ERR_WARN;
3718
3719 if (!*args[1]) {
3720 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3721 file, linenum, args[0]);
3722 err_code |= ERR_ALERT | ERR_FATAL;
3723 goto out;
3724 }
3725
3726 /* set the desired header name */
3727 free(curproxy->server_id_hdr_name);
3728 curproxy->server_id_hdr_name = strdup(args[1]);
3729 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3730 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003731 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003732 struct act_rule *rule;
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003733
Willy Tarreaub099aca2008-10-12 17:26:37 +02003734 if (curproxy == &defproxy) {
3735 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003736 err_code |= ERR_ALERT | ERR_FATAL;
3737 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003738 }
3739
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003740 /* emulate "block" using "http-request block". Since these rules are supposed to
3741 * be processed before all http-request rules, we put them into their own list
3742 * and will insert them at the end.
3743 */
3744 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3745 if (!rule) {
3746 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003747 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003748 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003749 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3750 err_code |= warnif_cond_conflicts(rule->cond,
3751 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3752 file, linenum);
3753 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003754
3755 if (!already_warned(WARN_BLOCK_DEPRECATED))
3756 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]);
3757
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003758 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003759 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003760 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003761
Cyril Bonté99ed3272010-01-24 23:29:44 +01003762 if (curproxy == &defproxy) {
3763 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3764 err_code |= ERR_ALERT | ERR_FATAL;
3765 goto out;
3766 }
3767
Willy Tarreaube4653b2015-05-28 15:26:58 +02003768 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003769 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3770 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003771 err_code |= ERR_ALERT | ERR_FATAL;
3772 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003773 }
3774
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003775 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003776 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003777 err_code |= warnif_cond_conflicts(rule->cond,
3778 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3779 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003780 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003781 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003782 struct switching_rule *rule;
3783
Willy Tarreaub099aca2008-10-12 17:26:37 +02003784 if (curproxy == &defproxy) {
3785 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003786 err_code |= ERR_ALERT | ERR_FATAL;
3787 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003788 }
3789
Willy Tarreau55ea7572007-06-17 19:56:27 +02003790 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003791 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003792
3793 if (*(args[1]) == 0) {
3794 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003795 err_code |= ERR_ALERT | ERR_FATAL;
3796 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003797 }
3798
Willy Tarreauf51658d2014-04-23 01:21:56 +02003799 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3800 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3801 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3802 file, linenum, errmsg);
3803 err_code |= ERR_ALERT | ERR_FATAL;
3804 goto out;
3805 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003806
Willy Tarreauf51658d2014-04-23 01:21:56 +02003807 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003808 }
3809
3810 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
3811 rule->cond = cond;
3812 rule->be.name = strdup(args[1]);
3813 LIST_INIT(&rule->list);
3814 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3815 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003816 else if (strcmp(args[0], "use-server") == 0) {
3817 struct server_rule *rule;
3818
3819 if (curproxy == &defproxy) {
3820 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3821 err_code |= ERR_ALERT | ERR_FATAL;
3822 goto out;
3823 }
3824
3825 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3826 err_code |= ERR_WARN;
3827
3828 if (*(args[1]) == 0) {
3829 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3830 err_code |= ERR_ALERT | ERR_FATAL;
3831 goto out;
3832 }
3833
3834 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3835 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3836 file, linenum, args[0]);
3837 err_code |= ERR_ALERT | ERR_FATAL;
3838 goto out;
3839 }
3840
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003841 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3842 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3843 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003844 err_code |= ERR_ALERT | ERR_FATAL;
3845 goto out;
3846 }
3847
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003848 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003849
3850 rule = (struct server_rule *)calloc(1, sizeof(*rule));
3851 rule->cond = cond;
3852 rule->srv.name = strdup(args[1]);
3853 LIST_INIT(&rule->list);
3854 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3855 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3856 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003857 else if ((!strcmp(args[0], "force-persist")) ||
3858 (!strcmp(args[0], "ignore-persist"))) {
3859 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003860
3861 if (curproxy == &defproxy) {
3862 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3863 err_code |= ERR_ALERT | ERR_FATAL;
3864 goto out;
3865 }
3866
3867 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3868 err_code |= ERR_WARN;
3869
Willy Tarreauef6494c2010-01-28 17:12:36 +01003870 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003871 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3872 file, linenum, args[0]);
3873 err_code |= ERR_ALERT | ERR_FATAL;
3874 goto out;
3875 }
3876
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003877 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3878 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3879 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003880 err_code |= ERR_ALERT | ERR_FATAL;
3881 goto out;
3882 }
3883
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003884 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3885 * where force-persist is applied.
3886 */
3887 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003888
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003889 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003890 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003891 if (!strcmp(args[0], "force-persist")) {
3892 rule->type = PERSIST_TYPE_FORCE;
3893 } else {
3894 rule->type = PERSIST_TYPE_IGNORE;
3895 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003896 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003897 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003898 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003899 else if (!strcmp(args[0], "stick-table")) {
3900 int myidx = 1;
Willy Tarreaue45288c2015-05-26 10:49:46 +02003901 struct proxy *other;
3902
Willy Tarreaue2dc1fa2015-05-26 12:08:07 +02003903 other = proxy_tbl_by_name(curproxy->id);
Willy Tarreaue45288c2015-05-26 10:49:46 +02003904 if (other) {
3905 Alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
3906 file, linenum, curproxy->id, proxy_type_str(other), other->id, other->conf.file, other->conf.line);
3907 err_code |= ERR_ALERT | ERR_FATAL;
3908 goto out;
3909 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003910
Emeric Brun32da3c42010-09-23 18:39:19 +02003911 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003912 curproxy->table.type = (unsigned int)-1;
3913 while (*args[myidx]) {
3914 const char *err;
3915
3916 if (strcmp(args[myidx], "size") == 0) {
3917 myidx++;
3918 if (!*(args[myidx])) {
3919 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3920 file, linenum, args[myidx-1]);
3921 err_code |= ERR_ALERT | ERR_FATAL;
3922 goto out;
3923 }
3924 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3925 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3926 file, linenum, *err, args[myidx-1]);
3927 err_code |= ERR_ALERT | ERR_FATAL;
3928 goto out;
3929 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003930 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003931 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003932 else if (strcmp(args[myidx], "peers") == 0) {
3933 myidx++;
Godbach50523162013-12-11 19:48:57 +08003934 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003935 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3936 file, linenum, args[myidx-1]);
3937 err_code |= ERR_ALERT | ERR_FATAL;
3938 goto out;
Godbach50523162013-12-11 19:48:57 +08003939 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003940 curproxy->table.peers.name = strdup(args[myidx++]);
3941 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003942 else if (strcmp(args[myidx], "expire") == 0) {
3943 myidx++;
3944 if (!*(args[myidx])) {
3945 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3946 file, linenum, args[myidx-1]);
3947 err_code |= ERR_ALERT | ERR_FATAL;
3948 goto out;
3949 }
3950 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3951 if (err) {
3952 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3953 file, linenum, *err, args[myidx-1]);
3954 err_code |= ERR_ALERT | ERR_FATAL;
3955 goto out;
3956 }
3957 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003958 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003959 }
3960 else if (strcmp(args[myidx], "nopurge") == 0) {
3961 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003962 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003963 }
3964 else if (strcmp(args[myidx], "type") == 0) {
3965 myidx++;
3966 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3967 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3968 file, linenum, args[myidx]);
3969 err_code |= ERR_ALERT | ERR_FATAL;
3970 goto out;
3971 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003972 /* myidx already points to next arg */
3973 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003974 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003975 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003976 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003977
3978 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003979 nw = args[myidx];
3980 while (*nw) {
3981 /* the "store" keyword supports a comma-separated list */
3982 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003983 sa = NULL; /* store arg */
3984 while (*nw && *nw != ',') {
3985 if (*nw == '(') {
3986 *nw = 0;
3987 sa = ++nw;
3988 while (*nw != ')') {
3989 if (!*nw) {
3990 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3991 file, linenum, args[0], cw);
3992 err_code |= ERR_ALERT | ERR_FATAL;
3993 goto out;
3994 }
3995 nw++;
3996 }
3997 *nw = '\0';
3998 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003999 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02004000 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004001 if (*nw)
4002 *nw++ = '\0';
4003 type = stktable_get_data_type(cw);
4004 if (type < 0) {
4005 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
4006 file, linenum, args[0], cw);
4007 err_code |= ERR_ALERT | ERR_FATAL;
4008 goto out;
4009 }
Willy Tarreauac782882010-06-20 10:41:54 +02004010
4011 err = stktable_alloc_data_type(&curproxy->table, type, sa);
4012 switch (err) {
4013 case PE_NONE: break;
4014 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004015 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
4016 file, linenum, args[0], cw);
4017 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02004018 break;
4019
4020 case PE_ARG_MISSING:
4021 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
4022 file, linenum, args[0], cw);
4023 err_code |= ERR_ALERT | ERR_FATAL;
4024 goto out;
4025
4026 case PE_ARG_NOT_USED:
4027 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
4028 file, linenum, args[0], cw);
4029 err_code |= ERR_ALERT | ERR_FATAL;
4030 goto out;
4031
4032 default:
4033 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
4034 file, linenum, args[0], cw);
4035 err_code |= ERR_ALERT | ERR_FATAL;
4036 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004037 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004038 }
4039 myidx++;
4040 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004041 else {
4042 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
4043 file, linenum, args[myidx]);
4044 err_code |= ERR_ALERT | ERR_FATAL;
4045 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004046 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004047 }
4048
4049 if (!curproxy->table.size) {
4050 Alert("parsing [%s:%d] : stick-table: missing size.\n",
4051 file, linenum);
4052 err_code |= ERR_ALERT | ERR_FATAL;
4053 goto out;
4054 }
4055
4056 if (curproxy->table.type == (unsigned int)-1) {
4057 Alert("parsing [%s:%d] : stick-table: missing type.\n",
4058 file, linenum);
4059 err_code |= ERR_ALERT | ERR_FATAL;
4060 goto out;
4061 }
4062 }
4063 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004064 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02004065 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004066 int myidx = 0;
4067 const char *name = NULL;
4068 int flags;
4069
4070 if (curproxy == &defproxy) {
4071 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4072 err_code |= ERR_ALERT | ERR_FATAL;
4073 goto out;
4074 }
4075
4076 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
4077 err_code |= ERR_WARN;
4078 goto out;
4079 }
4080
4081 myidx++;
4082 if ((strcmp(args[myidx], "store") == 0) ||
4083 (strcmp(args[myidx], "store-request") == 0)) {
4084 myidx++;
4085 flags = STK_IS_STORE;
4086 }
4087 else if (strcmp(args[myidx], "store-response") == 0) {
4088 myidx++;
4089 flags = STK_IS_STORE | STK_ON_RSP;
4090 }
4091 else if (strcmp(args[myidx], "match") == 0) {
4092 myidx++;
4093 flags = STK_IS_MATCH;
4094 }
4095 else if (strcmp(args[myidx], "on") == 0) {
4096 myidx++;
4097 flags = STK_IS_MATCH | STK_IS_STORE;
4098 }
4099 else {
4100 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
4101 err_code |= ERR_ALERT | ERR_FATAL;
4102 goto out;
4103 }
4104
4105 if (*(args[myidx]) == 0) {
4106 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
4107 err_code |= ERR_ALERT | ERR_FATAL;
4108 goto out;
4109 }
4110
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004111 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01004112 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004113 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01004114 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004115 err_code |= ERR_ALERT | ERR_FATAL;
4116 goto out;
4117 }
4118
4119 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01004120 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
4121 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
4122 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004123 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004124 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004125 goto out;
4126 }
4127 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01004128 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
4129 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
4130 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004131 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004132 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004133 goto out;
4134 }
4135 }
4136
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004137 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01004138 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004139
Emeric Brunb982a3d2010-01-04 15:45:53 +01004140 if (strcmp(args[myidx], "table") == 0) {
4141 myidx++;
4142 name = args[myidx++];
4143 }
4144
Willy Tarreauef6494c2010-01-28 17:12:36 +01004145 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004146 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
4147 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
4148 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004149 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004150 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004151 goto out;
4152 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004153 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01004154 else if (*(args[myidx])) {
4155 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
4156 file, linenum, args[0], args[myidx]);
4157 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004158 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01004159 goto out;
4160 }
Emeric Brun97679e72010-09-23 17:56:44 +02004161 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004162 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02004163 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004164 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01004165
Emeric Brunb982a3d2010-01-04 15:45:53 +01004166 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
4167 rule->cond = cond;
4168 rule->expr = expr;
4169 rule->flags = flags;
4170 rule->table.name = name ? strdup(name) : NULL;
4171 LIST_INIT(&rule->list);
4172 if (flags & STK_ON_RSP)
4173 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
4174 else
4175 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
4176 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004177 else if (!strcmp(args[0], "stats")) {
4178 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
4179 curproxy->uri_auth = NULL; /* we must detach from the default config */
4180
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004181 if (!*args[1]) {
4182 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02004183 } else if (!strcmp(args[1], "admin")) {
4184 struct stats_admin_rule *rule;
4185
4186 if (curproxy == &defproxy) {
4187 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
4188 err_code |= ERR_ALERT | ERR_FATAL;
4189 goto out;
4190 }
4191
4192 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4193 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4194 err_code |= ERR_ALERT | ERR_ABORT;
4195 goto out;
4196 }
4197
4198 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4199 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4200 file, linenum, args[0], args[1]);
4201 err_code |= ERR_ALERT | ERR_FATAL;
4202 goto out;
4203 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004204 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4205 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
4206 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02004207 err_code |= ERR_ALERT | ERR_FATAL;
4208 goto out;
4209 }
4210
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004211 err_code |= warnif_cond_conflicts(cond,
4212 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4213 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02004214
4215 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
4216 rule->cond = cond;
4217 LIST_INIT(&rule->list);
4218 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004219 } else if (!strcmp(args[1], "uri")) {
4220 if (*(args[2]) == 0) {
4221 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004222 err_code |= ERR_ALERT | ERR_FATAL;
4223 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004224 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
4225 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004226 err_code |= ERR_ALERT | ERR_ABORT;
4227 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004228 }
4229 } else if (!strcmp(args[1], "realm")) {
4230 if (*(args[2]) == 0) {
4231 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004232 err_code |= ERR_ALERT | ERR_FATAL;
4233 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004234 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
4235 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004236 err_code |= ERR_ALERT | ERR_ABORT;
4237 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004238 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02004239 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004240 unsigned interval;
4241
4242 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
4243 if (err) {
4244 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
4245 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004246 err_code |= ERR_ALERT | ERR_FATAL;
4247 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004248 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
4249 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004250 err_code |= ERR_ALERT | ERR_ABORT;
4251 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004252 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004253 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004254 struct act_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004255
4256 if (curproxy == &defproxy) {
4257 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4258 err_code |= ERR_ALERT | ERR_FATAL;
4259 goto out;
4260 }
4261
4262 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4263 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4264 err_code |= ERR_ALERT | ERR_ABORT;
4265 goto out;
4266 }
4267
Willy Tarreauff011f22011-01-06 17:51:27 +01004268 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004269 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct act_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004270 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
4271 file, linenum, args[0]);
4272 err_code |= ERR_WARN;
4273 }
4274
Willy Tarreauff011f22011-01-06 17:51:27 +01004275 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004276
Willy Tarreauff011f22011-01-06 17:51:27 +01004277 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004278 err_code |= ERR_ALERT | ERR_ABORT;
4279 goto out;
4280 }
4281
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004282 err_code |= warnif_cond_conflicts(rule->cond,
4283 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4284 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01004285 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004286
Willy Tarreaubaaee002006-06-26 02:48:02 +02004287 } else if (!strcmp(args[1], "auth")) {
4288 if (*(args[2]) == 0) {
4289 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004290 err_code |= ERR_ALERT | ERR_FATAL;
4291 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004292 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
4293 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004294 err_code |= ERR_ALERT | ERR_ABORT;
4295 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004296 }
4297 } else if (!strcmp(args[1], "scope")) {
4298 if (*(args[2]) == 0) {
4299 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004300 err_code |= ERR_ALERT | ERR_FATAL;
4301 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004302 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
4303 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004304 err_code |= ERR_ALERT | ERR_ABORT;
4305 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004306 }
4307 } else if (!strcmp(args[1], "enable")) {
4308 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4309 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004310 err_code |= ERR_ALERT | ERR_ABORT;
4311 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004312 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004313 } else if (!strcmp(args[1], "hide-version")) {
4314 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
4315 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004316 err_code |= ERR_ALERT | ERR_ABORT;
4317 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004318 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01004319 } else if (!strcmp(args[1], "show-legends")) {
4320 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
4321 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4322 err_code |= ERR_ALERT | ERR_ABORT;
4323 goto out;
4324 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004325 } else if (!strcmp(args[1], "show-node")) {
4326
4327 if (*args[2]) {
4328 int i;
4329 char c;
4330
4331 for (i=0; args[2][i]; i++) {
4332 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01004333 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
4334 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004335 break;
4336 }
4337
4338 if (!i || args[2][i]) {
4339 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
4340 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
4341 file, linenum, args[0], args[1]);
4342 err_code |= ERR_ALERT | ERR_FATAL;
4343 goto out;
4344 }
4345 }
4346
4347 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
4348 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4349 err_code |= ERR_ALERT | ERR_ABORT;
4350 goto out;
4351 }
4352 } else if (!strcmp(args[1], "show-desc")) {
4353 char *desc = NULL;
4354
4355 if (*args[2]) {
4356 int i, len=0;
4357 char *d;
4358
Willy Tarreau348acfe2014-04-14 15:00:39 +02004359 for (i = 2; *args[i]; i++)
4360 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004361
4362 desc = d = (char *)calloc(1, len);
4363
Willy Tarreau348acfe2014-04-14 15:00:39 +02004364 d += snprintf(d, desc + len - d, "%s", args[2]);
4365 for (i = 3; *args[i]; i++)
4366 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004367 }
4368
4369 if (!*args[2] && !global.desc)
4370 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
4371 file, linenum, args[1]);
4372 else {
4373 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
4374 free(desc);
4375 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4376 err_code |= ERR_ALERT | ERR_ABORT;
4377 goto out;
4378 }
4379 free(desc);
4380 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004381 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004382stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02004383 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 +01004384 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004385 err_code |= ERR_ALERT | ERR_FATAL;
4386 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004387 }
4388 }
4389 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004390 int optnum;
4391
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004392 if (*(args[1]) == '\0') {
4393 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
4394 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004395 err_code |= ERR_ALERT | ERR_FATAL;
4396 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004397 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01004398
4399 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
4400 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004401 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
4402 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4403 file, linenum, cfg_opts[optnum].name);
4404 err_code |= ERR_ALERT | ERR_FATAL;
4405 goto out;
4406 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004407 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4408 goto out;
4409
Willy Tarreau93893792009-07-23 13:19:11 +02004410 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
4411 err_code |= ERR_WARN;
4412 goto out;
4413 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004414
Willy Tarreau3842f002009-06-14 11:39:52 +02004415 curproxy->no_options &= ~cfg_opts[optnum].val;
4416 curproxy->options &= ~cfg_opts[optnum].val;
4417
4418 switch (kwm) {
4419 case KWM_STD:
4420 curproxy->options |= cfg_opts[optnum].val;
4421 break;
4422 case KWM_NO:
4423 curproxy->no_options |= cfg_opts[optnum].val;
4424 break;
4425 case KWM_DEF: /* already cleared */
4426 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004427 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004428
Willy Tarreau93893792009-07-23 13:19:11 +02004429 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004430 }
4431 }
4432
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004433 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
4434 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004435 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
4436 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4437 file, linenum, cfg_opts2[optnum].name);
4438 err_code |= ERR_ALERT | ERR_FATAL;
4439 goto out;
4440 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004441 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4442 goto out;
Willy Tarreau93893792009-07-23 13:19:11 +02004443 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4444 err_code |= ERR_WARN;
4445 goto out;
4446 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004447
Willy Tarreau3842f002009-06-14 11:39:52 +02004448 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4449 curproxy->options2 &= ~cfg_opts2[optnum].val;
4450
4451 switch (kwm) {
4452 case KWM_STD:
4453 curproxy->options2 |= cfg_opts2[optnum].val;
4454 break;
4455 case KWM_NO:
4456 curproxy->no_options2 |= cfg_opts2[optnum].val;
4457 break;
4458 case KWM_DEF: /* already cleared */
4459 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004460 }
Willy Tarreau93893792009-07-23 13:19:11 +02004461 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004462 }
4463 }
4464
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004465 /* HTTP options override each other. They can be cancelled using
4466 * "no option xxx" which only switches to default mode if the mode
4467 * was this one (useful for cancelling options set in defaults
4468 * sections).
4469 */
4470 if (strcmp(args[1], "httpclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004471 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4472 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004473 if (kwm == KWM_STD) {
4474 curproxy->options &= ~PR_O_HTTP_MODE;
4475 curproxy->options |= PR_O_HTTP_PCL;
4476 goto out;
4477 }
4478 else if (kwm == KWM_NO) {
4479 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4480 curproxy->options &= ~PR_O_HTTP_MODE;
4481 goto out;
4482 }
4483 }
4484 else if (strcmp(args[1], "forceclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004485 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4486 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004487 if (kwm == KWM_STD) {
4488 curproxy->options &= ~PR_O_HTTP_MODE;
4489 curproxy->options |= PR_O_HTTP_FCL;
4490 goto out;
4491 }
4492 else if (kwm == KWM_NO) {
4493 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4494 curproxy->options &= ~PR_O_HTTP_MODE;
4495 goto out;
4496 }
4497 }
4498 else if (strcmp(args[1], "http-server-close") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004499 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4500 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004501 if (kwm == KWM_STD) {
4502 curproxy->options &= ~PR_O_HTTP_MODE;
4503 curproxy->options |= PR_O_HTTP_SCL;
4504 goto out;
4505 }
4506 else if (kwm == KWM_NO) {
4507 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4508 curproxy->options &= ~PR_O_HTTP_MODE;
4509 goto out;
4510 }
4511 }
4512 else if (strcmp(args[1], "http-keep-alive") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004513 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4514 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004515 if (kwm == KWM_STD) {
4516 curproxy->options &= ~PR_O_HTTP_MODE;
4517 curproxy->options |= PR_O_HTTP_KAL;
4518 goto out;
4519 }
4520 else if (kwm == KWM_NO) {
4521 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4522 curproxy->options &= ~PR_O_HTTP_MODE;
4523 goto out;
4524 }
4525 }
4526 else if (strcmp(args[1], "http-tunnel") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004527 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4528 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004529 if (kwm == KWM_STD) {
4530 curproxy->options &= ~PR_O_HTTP_MODE;
4531 curproxy->options |= PR_O_HTTP_TUN;
4532 goto out;
4533 }
4534 else if (kwm == KWM_NO) {
4535 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4536 curproxy->options &= ~PR_O_HTTP_MODE;
4537 goto out;
4538 }
4539 }
4540
Joseph Lynch726ab712015-05-11 23:25:34 -07004541 /* Redispatch can take an integer argument that control when the
4542 * resispatch occurs. All values are relative to the retries option.
4543 * This can be cancelled using "no option xxx".
4544 */
4545 if (strcmp(args[1], "redispatch") == 0) {
4546 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
4547 err_code |= ERR_WARN;
4548 goto out;
4549 }
4550
4551 curproxy->no_options &= ~PR_O_REDISP;
4552 curproxy->options &= ~PR_O_REDISP;
4553
4554 switch (kwm) {
4555 case KWM_STD:
4556 curproxy->options |= PR_O_REDISP;
4557 curproxy->redispatch_after = -1;
4558 if(*args[2]) {
4559 curproxy->redispatch_after = atol(args[2]);
4560 }
4561 break;
4562 case KWM_NO:
4563 curproxy->no_options |= PR_O_REDISP;
4564 curproxy->redispatch_after = 0;
4565 break;
4566 case KWM_DEF: /* already cleared */
4567 break;
4568 }
4569 goto out;
4570 }
4571
Willy Tarreau3842f002009-06-14 11:39:52 +02004572 if (kwm != KWM_STD) {
4573 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004574 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004575 err_code |= ERR_ALERT | ERR_FATAL;
4576 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004577 }
4578
Emeric Brun3a058f32009-06-30 18:26:00 +02004579 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004580 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004581 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004582 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004583 if (*(args[2]) != '\0') {
4584 if (!strcmp(args[2], "clf")) {
4585 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004586 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004587 } else {
William Lallemand77063bc2015-05-28 18:02:48 +02004588 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004589 err_code |= ERR_ALERT | ERR_FATAL;
4590 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004591 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004592 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
4593 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004594 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004595 if (curproxy->conf.logformat_string != default_http_log_format &&
4596 curproxy->conf.logformat_string != default_tcp_log_format &&
4597 curproxy->conf.logformat_string != clf_http_log_format)
4598 free(curproxy->conf.logformat_string);
4599 curproxy->conf.logformat_string = logformat;
4600
4601 free(curproxy->conf.lfs_file);
4602 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4603 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004604 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004605 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004606 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004607 if (curproxy->conf.logformat_string != default_http_log_format &&
4608 curproxy->conf.logformat_string != default_tcp_log_format &&
4609 curproxy->conf.logformat_string != clf_http_log_format)
4610 free(curproxy->conf.logformat_string);
4611 curproxy->conf.logformat_string = default_tcp_log_format;
4612
4613 free(curproxy->conf.lfs_file);
4614 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4615 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemanddf1425a2015-04-28 20:17:49 +02004616
4617 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4618 goto out;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004619 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004620 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004621 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004622 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004623 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004624
William Lallemanddf1425a2015-04-28 20:17:49 +02004625 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4626 goto out;
4627
Willy Tarreau13943ab2006-12-31 00:24:10 +01004628 if (curproxy->cap & PR_CAP_FE)
4629 curproxy->options |= PR_O_TCP_CLI_KA;
4630 if (curproxy->cap & PR_CAP_BE)
4631 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004632 }
4633 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004634 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004635 err_code |= ERR_WARN;
4636
Willy Tarreaubaaee002006-06-26 02:48:02 +02004637 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004638 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004639 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004640 curproxy->options2 &= ~PR_O2_CHK_ANY;
4641 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004642 if (!*args[2]) { /* no argument */
4643 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4644 curproxy->check_len = strlen(DEF_CHECK_REQ);
4645 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004646 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004647 curproxy->check_req = (char *)malloc(reqlen);
4648 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004649 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004650 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004651 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004652 if (*args[4])
4653 reqlen += strlen(args[4]);
4654 else
4655 reqlen += strlen("HTTP/1.0");
4656
4657 curproxy->check_req = (char *)malloc(reqlen);
4658 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004659 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004660 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004661 if (alertif_too_many_args_idx(3, 1, file, linenum, args, &err_code))
4662 goto out;
Willy Tarreauf3c69202006-07-09 16:42:34 +02004663 }
4664 else if (!strcmp(args[1], "ssl-hello-chk")) {
4665 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004666 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004667 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004668
Willy Tarreaua534fea2008-08-03 12:19:50 +02004669 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004670 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004671 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004672 curproxy->options2 |= PR_O2_SSL3_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004673
4674 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4675 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004676 }
Willy Tarreau23677902007-05-08 23:50:35 +02004677 else if (!strcmp(args[1], "smtpchk")) {
4678 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004679 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004680 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004681 curproxy->options2 &= ~PR_O2_CHK_ANY;
4682 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004683
4684 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4685 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4686 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4687 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4688 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4689 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
4690 curproxy->check_req = (char *)malloc(reqlen);
4691 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4692 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4693 } else {
4694 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4695 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4696 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4697 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4698 }
4699 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004700 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4701 goto out;
Willy Tarreau23677902007-05-08 23:50:35 +02004702 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004703 else if (!strcmp(args[1], "pgsql-check")) {
4704 /* use PostgreSQL request to check servers' health */
4705 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4706 err_code |= ERR_WARN;
4707
4708 free(curproxy->check_req);
4709 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004710 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004711 curproxy->options2 |= PR_O2_PGSQL_CHK;
4712
4713 if (*(args[2])) {
4714 int cur_arg = 2;
4715
4716 while (*(args[cur_arg])) {
4717 if (strcmp(args[cur_arg], "user") == 0) {
4718 char * packet;
4719 uint32_t packet_len;
4720 uint32_t pv;
4721
4722 /* suboption header - needs additional argument for it */
4723 if (*(args[cur_arg+1]) == 0) {
4724 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4725 file, linenum, args[0], args[1], args[cur_arg]);
4726 err_code |= ERR_ALERT | ERR_FATAL;
4727 goto out;
4728 }
4729
4730 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4731 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4732 pv = htonl(0x30000); /* protocol version 3.0 */
4733
4734 packet = (char*) calloc(1, packet_len);
4735
4736 memcpy(packet + 4, &pv, 4);
4737
4738 /* copy "user" */
4739 memcpy(packet + 8, "user", 4);
4740
4741 /* copy username */
4742 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4743
4744 free(curproxy->check_req);
4745 curproxy->check_req = packet;
4746 curproxy->check_len = packet_len;
4747
4748 packet_len = htonl(packet_len);
4749 memcpy(packet, &packet_len, 4);
4750 cur_arg += 2;
4751 } else {
4752 /* unknown suboption - catchall */
4753 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4754 file, linenum, args[0], args[1]);
4755 err_code |= ERR_ALERT | ERR_FATAL;
4756 goto out;
4757 }
4758 } /* end while loop */
4759 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004760 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4761 goto out;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004762 }
4763
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004764 else if (!strcmp(args[1], "redis-check")) {
4765 /* use REDIS PING request to check servers' health */
4766 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4767 err_code |= ERR_WARN;
4768
4769 free(curproxy->check_req);
4770 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004771 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004772 curproxy->options2 |= PR_O2_REDIS_CHK;
4773
4774 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
4775 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4776 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004777
4778 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4779 goto out;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004780 }
4781
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004782 else if (!strcmp(args[1], "mysql-check")) {
4783 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004784 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4785 err_code |= ERR_WARN;
4786
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004787 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004788 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004789 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004790 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004791
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004792 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004793 * const char mysql40_client_auth_pkt[] = {
4794 * "\x0e\x00\x00" // packet length
4795 * "\x01" // packet number
4796 * "\x00\x00" // client capabilities
4797 * "\x00\x00\x01" // max packet
4798 * "haproxy\x00" // username (null terminated string)
4799 * "\x00" // filler (always 0x00)
4800 * "\x01\x00\x00" // packet length
4801 * "\x00" // packet number
4802 * "\x01" // COM_QUIT command
4803 * };
4804 */
4805
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004806 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4807 * const char mysql41_client_auth_pkt[] = {
4808 * "\x0e\x00\x00\" // packet length
4809 * "\x01" // packet number
4810 * "\x00\x00\x00\x00" // client capabilities
4811 * "\x00\x00\x00\x01" // max packet
4812 * "\x21" // character set (UTF-8)
4813 * char[23] // All zeroes
4814 * "haproxy\x00" // username (null terminated string)
4815 * "\x00" // filler (always 0x00)
4816 * "\x01\x00\x00" // packet length
4817 * "\x00" // packet number
4818 * "\x01" // COM_QUIT command
4819 * };
4820 */
4821
4822
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004823 if (*(args[2])) {
4824 int cur_arg = 2;
4825
4826 while (*(args[cur_arg])) {
4827 if (strcmp(args[cur_arg], "user") == 0) {
4828 char *mysqluser;
4829 int packetlen, reqlen, userlen;
4830
4831 /* suboption header - needs additional argument for it */
4832 if (*(args[cur_arg+1]) == 0) {
4833 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4834 file, linenum, args[0], args[1], args[cur_arg]);
4835 err_code |= ERR_ALERT | ERR_FATAL;
4836 goto out;
4837 }
4838 mysqluser = args[cur_arg + 1];
4839 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004840
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004841 if (*(args[cur_arg+2])) {
4842 if (!strcmp(args[cur_arg+2], "post-41")) {
4843 packetlen = userlen + 7 + 27;
4844 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004845
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004846 free(curproxy->check_req);
4847 curproxy->check_req = (char *)calloc(1, reqlen);
4848 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004849
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004850 snprintf(curproxy->check_req, 4, "%c%c%c",
4851 ((unsigned char) packetlen & 0xff),
4852 ((unsigned char) (packetlen >> 8) & 0xff),
4853 ((unsigned char) (packetlen >> 16) & 0xff));
4854
4855 curproxy->check_req[3] = 1;
4856 curproxy->check_req[5] = 130;
4857 curproxy->check_req[11] = 1;
4858 curproxy->check_req[12] = 33;
4859 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4860 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4861 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4862 cur_arg += 3;
4863 } else {
4864 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4865 err_code |= ERR_ALERT | ERR_FATAL;
4866 goto out;
4867 }
4868 } else {
4869 packetlen = userlen + 7;
4870 reqlen = packetlen + 9;
4871
4872 free(curproxy->check_req);
4873 curproxy->check_req = (char *)calloc(1, reqlen);
4874 curproxy->check_len = reqlen;
4875
4876 snprintf(curproxy->check_req, 4, "%c%c%c",
4877 ((unsigned char) packetlen & 0xff),
4878 ((unsigned char) (packetlen >> 8) & 0xff),
4879 ((unsigned char) (packetlen >> 16) & 0xff));
4880
4881 curproxy->check_req[3] = 1;
4882 curproxy->check_req[5] = 128;
4883 curproxy->check_req[8] = 1;
4884 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4885 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4886 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4887 cur_arg += 2;
4888 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004889 } else {
4890 /* unknown suboption - catchall */
4891 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4892 file, linenum, args[0], args[1]);
4893 err_code |= ERR_ALERT | ERR_FATAL;
4894 goto out;
4895 }
4896 } /* end while loop */
4897 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004898 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004899 else if (!strcmp(args[1], "ldap-check")) {
4900 /* use LDAP request to check servers' health */
4901 free(curproxy->check_req);
4902 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004903 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004904 curproxy->options2 |= PR_O2_LDAP_CHK;
4905
4906 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
4907 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
4908 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004909 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4910 goto out;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004911 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004912 else if (!strcmp(args[1], "tcp-check")) {
4913 /* use raw TCPCHK send/expect to check servers' health */
4914 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4915 err_code |= ERR_WARN;
4916
4917 free(curproxy->check_req);
4918 curproxy->check_req = NULL;
4919 curproxy->options2 &= ~PR_O2_CHK_ANY;
4920 curproxy->options2 |= PR_O2_TCPCHK_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004921 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4922 goto out;
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004923 }
Simon Horman98637e52014-06-20 12:30:16 +09004924 else if (!strcmp(args[1], "external-check")) {
4925 /* excute an external command to check servers' health */
4926 free(curproxy->check_req);
4927 curproxy->check_req = NULL;
4928 curproxy->options2 &= ~PR_O2_CHK_ANY;
4929 curproxy->options2 |= PR_O2_EXT_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004930 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4931 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09004932 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004933 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004934 int cur_arg;
4935
4936 /* insert x-forwarded-for field, but not for the IP address listed as an except.
4937 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004938 */
Ross Westaf72a1d2008-08-03 10:51:45 +02004939
Willy Tarreau87cf5142011-08-19 22:57:24 +02004940 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02004941
4942 free(curproxy->fwdfor_hdr_name);
4943 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
4944 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
4945
4946 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
4947 cur_arg = 2;
4948 while (*(args[cur_arg])) {
4949 if (!strcmp(args[cur_arg], "except")) {
4950 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004951 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004952 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4953 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004954 err_code |= ERR_ALERT | ERR_FATAL;
4955 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004956 }
4957 /* flush useless bits */
4958 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02004959 cur_arg += 2;
4960 } else if (!strcmp(args[cur_arg], "header")) {
4961 /* suboption header - needs additional argument for it */
4962 if (*(args[cur_arg+1]) == 0) {
4963 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4964 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004965 err_code |= ERR_ALERT | ERR_FATAL;
4966 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02004967 }
4968 free(curproxy->fwdfor_hdr_name);
4969 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
4970 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
4971 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02004972 } else if (!strcmp(args[cur_arg], "if-none")) {
4973 curproxy->options &= ~PR_O_FF_ALWAYS;
4974 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004975 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02004976 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02004977 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02004978 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004979 err_code |= ERR_ALERT | ERR_FATAL;
4980 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004981 }
Ross Westaf72a1d2008-08-03 10:51:45 +02004982 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004983 }
Maik Broemme2850cb42009-04-17 18:53:21 +02004984 else if (!strcmp(args[1], "originalto")) {
4985 int cur_arg;
4986
4987 /* insert x-original-to field, but not for the IP address listed as an except.
4988 * set default options (ie: bitfield, header name, etc)
4989 */
4990
4991 curproxy->options |= PR_O_ORGTO;
4992
4993 free(curproxy->orgto_hdr_name);
4994 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
4995 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
4996
Willy Tarreau87cf5142011-08-19 22:57:24 +02004997 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02004998 cur_arg = 2;
4999 while (*(args[cur_arg])) {
5000 if (!strcmp(args[cur_arg], "except")) {
5001 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005002 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 +02005003 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5004 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005005 err_code |= ERR_ALERT | ERR_FATAL;
5006 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005007 }
5008 /* flush useless bits */
5009 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
5010 cur_arg += 2;
5011 } else if (!strcmp(args[cur_arg], "header")) {
5012 /* suboption header - needs additional argument for it */
5013 if (*(args[cur_arg+1]) == 0) {
5014 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5015 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005016 err_code |= ERR_ALERT | ERR_FATAL;
5017 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005018 }
5019 free(curproxy->orgto_hdr_name);
5020 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
5021 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
5022 cur_arg += 2;
5023 } else {
5024 /* unknown suboption - catchall */
5025 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
5026 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005027 err_code |= ERR_ALERT | ERR_FATAL;
5028 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005029 }
5030 } /* end while loop */
5031 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005032 else {
5033 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005034 err_code |= ERR_ALERT | ERR_FATAL;
5035 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005036 }
Willy Tarreau93893792009-07-23 13:19:11 +02005037 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005038 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005039 else if (!strcmp(args[0], "default_backend")) {
5040 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005041 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005042
5043 if (*(args[1]) == 0) {
5044 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005045 err_code |= ERR_ALERT | ERR_FATAL;
5046 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005047 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005048 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005049 curproxy->defbe.name = strdup(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005050
5051 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5052 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005053 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005054 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01005055 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005056 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005057
Willy Tarreaua3c504c2014-04-28 22:37:32 +02005058 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
5059 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 +01005060 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005061 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005062 /* enable reconnections to dispatch */
5063 curproxy->options |= PR_O_REDISP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005064
5065 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5066 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005067 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005068 else if (!strcmp(args[0], "http-reuse")) {
5069 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5070 err_code |= ERR_WARN;
5071
5072 if (strcmp(args[1], "never") == 0) {
5073 /* enable a graceful server shutdown on an HTTP 404 response */
5074 curproxy->options &= ~PR_O_REUSE_MASK;
5075 curproxy->options |= PR_O_REUSE_NEVR;
5076 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5077 goto out;
5078 }
Willy Tarreau161d45f2015-08-05 16:02:46 +02005079 else if (strcmp(args[1], "safe") == 0) {
5080 /* enable a graceful server shutdown on an HTTP 404 response */
5081 curproxy->options &= ~PR_O_REUSE_MASK;
5082 curproxy->options |= PR_O_REUSE_SAFE;
5083 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5084 goto out;
5085 }
Willy Tarreau449d74a2015-08-05 17:16:33 +02005086 else if (strcmp(args[1], "aggressive") == 0) {
5087 curproxy->options &= ~PR_O_REUSE_MASK;
5088 curproxy->options |= PR_O_REUSE_AGGR;
5089 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5090 goto out;
5091 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005092 else if (strcmp(args[1], "always") == 0) {
5093 /* enable a graceful server shutdown on an HTTP 404 response */
5094 curproxy->options &= ~PR_O_REUSE_MASK;
5095 curproxy->options |= PR_O_REUSE_ALWS;
5096 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5097 goto out;
5098 }
5099 else {
Willy Tarreau449d74a2015-08-05 17:16:33 +02005100 Alert("parsing [%s:%d] : '%s' only supports 'never', 'safe', 'aggressive', 'always'.\n", file, linenum, args[0]);
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005101 err_code |= ERR_ALERT | ERR_FATAL;
5102 goto out;
5103 }
5104 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005105 else if (!strcmp(args[0], "http-check")) {
5106 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005107 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01005108
5109 if (strcmp(args[1], "disable-on-404") == 0) {
5110 /* enable a graceful server shutdown on an HTTP 404 response */
5111 curproxy->options |= PR_O_DISABLE404;
William Lallemanddf1425a2015-04-28 20:17:49 +02005112 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5113 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005114 }
Willy Tarreauef781042010-01-27 11:53:01 +01005115 else if (strcmp(args[1], "send-state") == 0) {
5116 /* enable emission of the apparent state of a server in HTTP checks */
5117 curproxy->options2 |= PR_O2_CHK_SNDST;
William Lallemanddf1425a2015-04-28 20:17:49 +02005118 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5119 goto out;
Willy Tarreauef781042010-01-27 11:53:01 +01005120 }
Willy Tarreaubd741542010-03-16 18:46:54 +01005121 else if (strcmp(args[1], "expect") == 0) {
5122 const char *ptr_arg;
5123 int cur_arg;
5124
5125 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5126 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5127 err_code |= ERR_ALERT | ERR_FATAL;
5128 goto out;
5129 }
5130
5131 cur_arg = 2;
5132 /* consider exclamation marks, sole or at the beginning of a word */
5133 while (*(ptr_arg = args[cur_arg])) {
5134 while (*ptr_arg == '!') {
5135 curproxy->options2 ^= PR_O2_EXP_INV;
5136 ptr_arg++;
5137 }
5138 if (*ptr_arg)
5139 break;
5140 cur_arg++;
5141 }
5142 /* now ptr_arg points to the beginning of a word past any possible
5143 * exclamation mark, and cur_arg is the argument which holds this word.
5144 */
5145 if (strcmp(ptr_arg, "status") == 0) {
5146 if (!*(args[cur_arg + 1])) {
5147 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5148 file, linenum, args[0], args[1], ptr_arg);
5149 err_code |= ERR_ALERT | ERR_FATAL;
5150 goto out;
5151 }
5152 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005153 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005154 curproxy->expect_str = strdup(args[cur_arg + 1]);
5155 }
5156 else if (strcmp(ptr_arg, "string") == 0) {
5157 if (!*(args[cur_arg + 1])) {
5158 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5159 file, linenum, args[0], args[1], ptr_arg);
5160 err_code |= ERR_ALERT | ERR_FATAL;
5161 goto out;
5162 }
5163 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005164 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005165 curproxy->expect_str = strdup(args[cur_arg + 1]);
5166 }
5167 else if (strcmp(ptr_arg, "rstatus") == 0) {
5168 if (!*(args[cur_arg + 1])) {
5169 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5170 file, linenum, args[0], args[1], ptr_arg);
5171 err_code |= ERR_ALERT | ERR_FATAL;
5172 goto out;
5173 }
5174 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005175 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005176 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005177 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005178 free(curproxy->expect_regex);
5179 curproxy->expect_regex = NULL;
5180 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005181 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005182 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5183 error = NULL;
5184 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5185 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5186 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5187 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005188 err_code |= ERR_ALERT | ERR_FATAL;
5189 goto out;
5190 }
5191 }
5192 else if (strcmp(ptr_arg, "rstring") == 0) {
5193 if (!*(args[cur_arg + 1])) {
5194 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5195 file, linenum, args[0], args[1], ptr_arg);
5196 err_code |= ERR_ALERT | ERR_FATAL;
5197 goto out;
5198 }
5199 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005200 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005201 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005202 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005203 free(curproxy->expect_regex);
5204 curproxy->expect_regex = NULL;
5205 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005206 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005207 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5208 error = NULL;
5209 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5210 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5211 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5212 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005213 err_code |= ERR_ALERT | ERR_FATAL;
5214 goto out;
5215 }
5216 }
5217 else {
5218 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
5219 file, linenum, args[0], args[1], ptr_arg);
5220 err_code |= ERR_ALERT | ERR_FATAL;
5221 goto out;
5222 }
5223 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005224 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005225 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 +02005226 err_code |= ERR_ALERT | ERR_FATAL;
5227 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005228 }
5229 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005230 else if (!strcmp(args[0], "tcp-check")) {
5231 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5232 err_code |= ERR_WARN;
5233
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005234 if (strcmp(args[1], "comment") == 0) {
5235 int cur_arg;
5236 struct tcpcheck_rule *tcpcheck;
5237
5238 cur_arg = 1;
5239 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5240 tcpcheck->action = TCPCHK_ACT_COMMENT;
5241
5242 if (!*args[cur_arg + 1]) {
5243 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5244 file, linenum, args[cur_arg]);
5245 err_code |= ERR_ALERT | ERR_FATAL;
5246 goto out;
5247 }
5248
5249 tcpcheck->comment = strdup(args[cur_arg + 1]);
5250
5251 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
William Lallemanddf1425a2015-04-28 20:17:49 +02005252 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
5253 goto out;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005254 }
5255 else if (strcmp(args[1], "connect") == 0) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005256 const char *ptr_arg;
5257 int cur_arg;
5258 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005259
5260 /* check if first rule is also a 'connect' action */
Willy Tarreau5581c272015-05-13 12:24:53 +02005261 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
5262 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
5263 tcpcheck->action == TCPCHK_ACT_COMMENT) {
5264 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
5265 }
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005266
Willy Tarreau5581c272015-05-13 12:24:53 +02005267 if (&tcpcheck->list != &curproxy->tcpcheck_rules
5268 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
5269 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
5270 file, linenum);
5271 err_code |= ERR_ALERT | ERR_FATAL;
5272 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005273 }
5274
5275 cur_arg = 2;
5276 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5277 tcpcheck->action = TCPCHK_ACT_CONNECT;
5278
5279 /* parsing each parameters to fill up the rule */
5280 while (*(ptr_arg = args[cur_arg])) {
5281 /* tcp port */
5282 if (strcmp(args[cur_arg], "port") == 0) {
5283 if ( (atol(args[cur_arg + 1]) > 65535) ||
5284 (atol(args[cur_arg + 1]) < 1) ){
5285 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
5286 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
5287 err_code |= ERR_ALERT | ERR_FATAL;
5288 goto out;
5289 }
5290 tcpcheck->port = atol(args[cur_arg + 1]);
5291 cur_arg += 2;
5292 }
5293 /* send proxy protocol */
5294 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
5295 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
5296 cur_arg++;
5297 }
5298#ifdef USE_OPENSSL
5299 else if (strcmp(args[cur_arg], "ssl") == 0) {
5300 curproxy->options |= PR_O_TCPCHK_SSL;
5301 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
5302 cur_arg++;
5303 }
5304#endif /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005305 /* comment for this tcpcheck line */
5306 else if (strcmp(args[cur_arg], "comment") == 0) {
5307 if (!*args[cur_arg + 1]) {
5308 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5309 file, linenum, args[cur_arg]);
5310 err_code |= ERR_ALERT | ERR_FATAL;
5311 goto out;
5312 }
5313 tcpcheck->comment = strdup(args[cur_arg + 1]);
5314 cur_arg += 2;
5315 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005316 else {
5317#ifdef USE_OPENSSL
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005318 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 +01005319#else /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005320 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 +01005321#endif /* USE_OPENSSL */
5322 file, linenum, args[0], args[1], args[cur_arg]);
5323 err_code |= ERR_ALERT | ERR_FATAL;
5324 goto out;
5325 }
5326
5327 }
5328
5329 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5330 }
5331 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005332 if (! *(args[2]) ) {
5333 /* SEND string expected */
5334 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
5335 file, linenum, args[0], args[1], args[2]);
5336 err_code |= ERR_ALERT | ERR_FATAL;
5337 goto out;
5338 } else {
5339 struct tcpcheck_rule *tcpcheck;
5340
5341 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5342
5343 tcpcheck->action = TCPCHK_ACT_SEND;
5344 tcpcheck->string_len = strlen(args[2]);
5345 tcpcheck->string = strdup(args[2]);
5346 tcpcheck->expect_regex = NULL;
5347
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005348 /* comment for this tcpcheck line */
5349 if (strcmp(args[3], "comment") == 0) {
5350 if (!*args[4]) {
5351 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5352 file, linenum, args[3]);
5353 err_code |= ERR_ALERT | ERR_FATAL;
5354 goto out;
5355 }
5356 tcpcheck->comment = strdup(args[4]);
5357 }
5358
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005359 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5360 }
5361 }
5362 else if (strcmp(args[1], "send-binary") == 0) {
5363 if (! *(args[2]) ) {
5364 /* SEND binary string expected */
5365 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
5366 file, linenum, args[0], args[1], args[2]);
5367 err_code |= ERR_ALERT | ERR_FATAL;
5368 goto out;
5369 } else {
5370 struct tcpcheck_rule *tcpcheck;
5371 char *err = NULL;
5372
5373 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5374
5375 tcpcheck->action = TCPCHK_ACT_SEND;
5376 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5377 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5378 file, linenum, args[0], args[1], args[2], err);
5379 err_code |= ERR_ALERT | ERR_FATAL;
5380 goto out;
5381 }
5382 tcpcheck->expect_regex = NULL;
5383
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005384 /* comment for this tcpcheck line */
5385 if (strcmp(args[3], "comment") == 0) {
5386 if (!*args[4]) {
5387 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5388 file, linenum, args[3]);
5389 err_code |= ERR_ALERT | ERR_FATAL;
5390 goto out;
5391 }
5392 tcpcheck->comment = strdup(args[4]);
5393 }
5394
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005395 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5396 }
5397 }
5398 else if (strcmp(args[1], "expect") == 0) {
5399 const char *ptr_arg;
5400 int cur_arg;
5401 int inverse = 0;
5402
5403 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5404 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5405 err_code |= ERR_ALERT | ERR_FATAL;
5406 goto out;
5407 }
5408
5409 cur_arg = 2;
5410 /* consider exclamation marks, sole or at the beginning of a word */
5411 while (*(ptr_arg = args[cur_arg])) {
5412 while (*ptr_arg == '!') {
5413 inverse = !inverse;
5414 ptr_arg++;
5415 }
5416 if (*ptr_arg)
5417 break;
5418 cur_arg++;
5419 }
5420 /* now ptr_arg points to the beginning of a word past any possible
5421 * exclamation mark, and cur_arg is the argument which holds this word.
5422 */
5423 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005424 struct tcpcheck_rule *tcpcheck;
5425 char *err = NULL;
5426
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005427 if (!*(args[cur_arg + 1])) {
5428 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
5429 file, linenum, args[0], args[1], ptr_arg);
5430 err_code |= ERR_ALERT | ERR_FATAL;
5431 goto out;
5432 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005433
5434 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5435
5436 tcpcheck->action = TCPCHK_ACT_EXPECT;
5437 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5438 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5439 file, linenum, args[0], args[1], args[2], err);
5440 err_code |= ERR_ALERT | ERR_FATAL;
5441 goto out;
5442 }
5443 tcpcheck->expect_regex = NULL;
5444 tcpcheck->inverse = inverse;
5445
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005446 /* tcpcheck comment */
5447 cur_arg += 2;
5448 if (strcmp(args[cur_arg], "comment") == 0) {
5449 if (!*args[cur_arg + 1]) {
5450 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5451 file, linenum, args[cur_arg + 1]);
5452 err_code |= ERR_ALERT | ERR_FATAL;
5453 goto out;
5454 }
5455 tcpcheck->comment = strdup(args[cur_arg + 1]);
5456 }
5457
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005458 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5459 }
5460 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005461 struct tcpcheck_rule *tcpcheck;
5462
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005463 if (!*(args[cur_arg + 1])) {
5464 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5465 file, linenum, args[0], args[1], ptr_arg);
5466 err_code |= ERR_ALERT | ERR_FATAL;
5467 goto out;
5468 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005469
5470 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5471
5472 tcpcheck->action = TCPCHK_ACT_EXPECT;
5473 tcpcheck->string_len = strlen(args[cur_arg + 1]);
5474 tcpcheck->string = strdup(args[cur_arg + 1]);
5475 tcpcheck->expect_regex = NULL;
5476 tcpcheck->inverse = inverse;
5477
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005478 /* tcpcheck comment */
5479 cur_arg += 2;
5480 if (strcmp(args[cur_arg], "comment") == 0) {
5481 if (!*args[cur_arg + 1]) {
5482 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5483 file, linenum, args[cur_arg + 1]);
5484 err_code |= ERR_ALERT | ERR_FATAL;
5485 goto out;
5486 }
5487 tcpcheck->comment = strdup(args[cur_arg + 1]);
5488 }
5489
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005490 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5491 }
5492 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005493 struct tcpcheck_rule *tcpcheck;
5494
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005495 if (!*(args[cur_arg + 1])) {
5496 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5497 file, linenum, args[0], args[1], ptr_arg);
5498 err_code |= ERR_ALERT | ERR_FATAL;
5499 goto out;
5500 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005501
5502 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5503
5504 tcpcheck->action = TCPCHK_ACT_EXPECT;
5505 tcpcheck->string_len = 0;
5506 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005507 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
5508 error = NULL;
5509 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
5510 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5511 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5512 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005513 err_code |= ERR_ALERT | ERR_FATAL;
5514 goto out;
5515 }
5516 tcpcheck->inverse = inverse;
5517
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005518 /* tcpcheck comment */
5519 cur_arg += 2;
5520 if (strcmp(args[cur_arg], "comment") == 0) {
5521 if (!*args[cur_arg + 1]) {
5522 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5523 file, linenum, args[cur_arg + 1]);
5524 err_code |= ERR_ALERT | ERR_FATAL;
5525 goto out;
5526 }
5527 tcpcheck->comment = strdup(args[cur_arg + 1]);
5528 }
5529
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005530 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5531 }
5532 else {
5533 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
5534 file, linenum, args[0], args[1], ptr_arg);
5535 err_code |= ERR_ALERT | ERR_FATAL;
5536 goto out;
5537 }
5538 }
5539 else {
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005540 Alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005541 err_code |= ERR_ALERT | ERR_FATAL;
5542 goto out;
5543 }
5544 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01005545 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02005546 if (curproxy == &defproxy) {
5547 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005548 err_code |= ERR_ALERT | ERR_FATAL;
5549 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02005550 }
5551
Willy Tarreaub80c2302007-11-30 20:51:32 +01005552 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005553 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005554
5555 if (strcmp(args[1], "fail") == 0) {
5556 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01005557 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01005558 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
5559 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005560 err_code |= ERR_ALERT | ERR_FATAL;
5561 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005562 }
5563
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005564 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
5565 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
5566 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005567 err_code |= ERR_ALERT | ERR_FATAL;
5568 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005569 }
5570 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
5571 }
5572 else {
5573 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005574 err_code |= ERR_ALERT | ERR_FATAL;
5575 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005576 }
5577 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005578#ifdef TPROXY
5579 else if (!strcmp(args[0], "transparent")) {
5580 /* enable transparent proxy connections */
5581 curproxy->options |= PR_O_TRANSP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005582 if (alertif_too_many_args(0, file, linenum, args, &err_code))
5583 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005584 }
5585#endif
5586 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005587 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005588 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005589
Willy Tarreaubaaee002006-06-26 02:48:02 +02005590 if (*(args[1]) == 0) {
5591 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005592 err_code |= ERR_ALERT | ERR_FATAL;
5593 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005594 }
5595 curproxy->maxconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005596 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5597 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005598 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005599 else if (!strcmp(args[0], "backlog")) { /* backlog */
5600 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005601 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005602
5603 if (*(args[1]) == 0) {
5604 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005605 err_code |= ERR_ALERT | ERR_FATAL;
5606 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005607 }
5608 curproxy->backlog = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005609 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5610 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005611 }
Willy Tarreau86034312006-12-29 00:10:33 +01005612 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005613 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005614 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005615
Willy Tarreau86034312006-12-29 00:10:33 +01005616 if (*(args[1]) == 0) {
5617 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005618 err_code |= ERR_ALERT | ERR_FATAL;
5619 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005620 }
5621 curproxy->fullconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005622 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5623 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005624 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005625 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
5626 if (*(args[1]) == 0) {
5627 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005628 err_code |= ERR_ALERT | ERR_FATAL;
5629 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005630 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005631 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
5632 if (err) {
5633 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
5634 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02005635 err_code |= ERR_ALERT | ERR_FATAL;
5636 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005637 }
5638 curproxy->grace = val;
William Lallemanddf1425a2015-04-28 20:17:49 +02005639 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5640 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005641 }
5642 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01005643 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005644 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005645 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005646
Willy Tarreaubaaee002006-06-26 02:48:02 +02005647 if (curproxy == &defproxy) {
5648 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005649 err_code |= ERR_ALERT | ERR_FATAL;
5650 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005651 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005652 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005653 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005654
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02005655 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005656 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005657 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005658 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005659 goto out;
5660 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005661
5662 proto = protocol_by_family(sk->ss_family);
5663 if (!proto || !proto->connect) {
5664 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5665 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005666 err_code |= ERR_ALERT | ERR_FATAL;
5667 goto out;
5668 }
5669
5670 if (port1 != port2) {
5671 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5672 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005673 err_code |= ERR_ALERT | ERR_FATAL;
5674 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005675 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005676
5677 if (!port1) {
5678 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5679 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005680 err_code |= ERR_ALERT | ERR_FATAL;
5681 goto out;
5682 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005683
William Lallemanddf1425a2015-04-28 20:17:49 +02005684 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5685 goto out;
5686
Willy Tarreaud5191e72010-02-09 20:50:45 +01005687 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005688 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005689 }
5690 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005691 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005692 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005693
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005694 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5695 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005696 err_code |= ERR_ALERT | ERR_FATAL;
5697 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005698 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005699 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005700 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005701 /**
5702 * The syntax for hash-type config element is
5703 * hash-type {map-based|consistent} [[<algo>] avalanche]
5704 *
5705 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5706 */
5707 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005708
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005709 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5710 err_code |= ERR_WARN;
5711
5712 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005713 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5714 }
5715 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005716 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5717 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005718 else if (strcmp(args[1], "avalanche") == 0) {
5719 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]);
5720 err_code |= ERR_ALERT | ERR_FATAL;
5721 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005722 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005723 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005724 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005725 err_code |= ERR_ALERT | ERR_FATAL;
5726 goto out;
5727 }
Bhaskar98634f02013-10-29 23:30:51 -04005728
5729 /* set the hash function to use */
5730 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005731 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005732 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005733
5734 /* if consistent with no argument, then avalanche modifier is also applied */
5735 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5736 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005737 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005738 /* set the hash function */
5739 if (!strcmp(args[2], "sdbm")) {
5740 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5741 }
5742 else if (!strcmp(args[2], "djb2")) {
5743 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005744 }
5745 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005746 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005747 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005748 else if (!strcmp(args[2], "crc32")) {
5749 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5750 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005751 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005752 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 -05005753 err_code |= ERR_ALERT | ERR_FATAL;
5754 goto out;
5755 }
5756
5757 /* set the hash modifier */
5758 if (!strcmp(args[3], "avalanche")) {
5759 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5760 }
5761 else if (*args[3]) {
5762 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5763 err_code |= ERR_ALERT | ERR_FATAL;
5764 goto out;
5765 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005766 }
William Lallemanda73203e2012-03-12 12:48:57 +01005767 }
William Lallemanda73203e2012-03-12 12:48:57 +01005768 else if (strcmp(args[0], "unique-id-format") == 0) {
5769 if (!*(args[1])) {
5770 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5771 err_code |= ERR_ALERT | ERR_FATAL;
5772 goto out;
5773 }
William Lallemand3203ff42012-11-11 17:30:56 +01005774 if (*(args[2])) {
5775 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5776 err_code |= ERR_ALERT | ERR_FATAL;
5777 goto out;
5778 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005779 free(curproxy->conf.uniqueid_format_string);
5780 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005781
Willy Tarreau62a61232013-04-12 18:13:46 +02005782 free(curproxy->conf.uif_file);
5783 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5784 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005785 }
William Lallemanda73203e2012-03-12 12:48:57 +01005786
5787 else if (strcmp(args[0], "unique-id-header") == 0) {
5788 if (!*(args[1])) {
5789 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5790 err_code |= ERR_ALERT | ERR_FATAL;
5791 goto out;
5792 }
5793 free(curproxy->header_unique_id);
5794 curproxy->header_unique_id = strdup(args[1]);
5795 }
5796
William Lallemand723b73a2012-02-08 16:37:49 +01005797 else if (strcmp(args[0], "log-format") == 0) {
5798 if (!*(args[1])) {
5799 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5800 err_code |= ERR_ALERT | ERR_FATAL;
5801 goto out;
5802 }
William Lallemand3203ff42012-11-11 17:30:56 +01005803 if (*(args[2])) {
5804 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5805 err_code |= ERR_ALERT | ERR_FATAL;
5806 goto out;
5807 }
Willy Tarreau196729e2012-05-31 19:30:26 +02005808
Willy Tarreau62a61232013-04-12 18:13:46 +02005809 if (curproxy->conf.logformat_string != default_http_log_format &&
5810 curproxy->conf.logformat_string != default_tcp_log_format &&
5811 curproxy->conf.logformat_string != clf_http_log_format)
5812 free(curproxy->conf.logformat_string);
5813 curproxy->conf.logformat_string = strdup(args[1]);
5814
5815 free(curproxy->conf.lfs_file);
5816 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5817 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005818
5819 /* get a chance to improve log-format error reporting by
5820 * reporting the correct line-number when possible.
5821 */
5822 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5823 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5824 file, linenum, curproxy->id);
5825 err_code |= ERR_WARN;
5826 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005827 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02005828 else if (!strcmp(args[0], "log-format-sd")) {
5829 if (!*(args[1])) {
5830 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5831 err_code |= ERR_ALERT | ERR_FATAL;
5832 goto out;
5833 }
5834 if (*(args[2])) {
5835 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5836 err_code |= ERR_ALERT | ERR_FATAL;
5837 goto out;
5838 }
5839
5840 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
5841 free(curproxy->conf.logformat_sd_string);
5842 curproxy->conf.logformat_sd_string = strdup(args[1]);
5843
5844 free(curproxy->conf.lfsd_file);
5845 curproxy->conf.lfsd_file = strdup(curproxy->conf.args.file);
5846 curproxy->conf.lfsd_line = curproxy->conf.args.line;
5847
5848 /* get a chance to improve log-format-sd error reporting by
5849 * reporting the correct line-number when possible.
5850 */
5851 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5852 Warning("parsing [%s:%d] : backend '%s' : 'log-format-sd' directive is ignored in backends.\n",
5853 file, linenum, curproxy->id);
5854 err_code |= ERR_WARN;
5855 }
5856 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01005857 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
5858 if (*(args[1]) == 0) {
5859 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
5860 err_code |= ERR_ALERT | ERR_FATAL;
5861 goto out;
5862 }
Dragan Dosen43885c72015-10-01 13:18:13 +02005863 chunk_destroy(&curproxy->log_tag);
5864 chunk_initstr(&curproxy->log_tag, strdup(args[1]));
Willy Tarreau094af4e2015-01-07 15:03:42 +01005865 }
William Lallemand0f99e342011-10-12 17:50:54 +02005866 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
5867 /* delete previous herited or defined syslog servers */
5868 struct logsrv *back;
5869
5870 if (*(args[1]) != 0) {
5871 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
5872 err_code |= ERR_ALERT | ERR_FATAL;
5873 goto out;
5874 }
5875
William Lallemand723b73a2012-02-08 16:37:49 +01005876 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
5877 LIST_DEL(&tmplogsrv->list);
5878 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02005879 }
5880 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005881 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02005882 struct logsrv *logsrv;
5883
Willy Tarreaubaaee002006-06-26 02:48:02 +02005884 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005885 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01005886 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02005887 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01005888 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02005889 LIST_INIT(&node->list);
5890 LIST_ADDQ(&curproxy->logsrvs, &node->list);
5891 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005892 }
5893 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005894 struct sockaddr_storage *sk;
5895 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02005896 int arg = 0;
5897 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02005898
5899 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005900
Willy Tarreau18324f52014-06-27 18:10:07 +02005901 /* just after the address, a length may be specified */
5902 if (strcmp(args[arg+2], "len") == 0) {
5903 len = atoi(args[arg+3]);
5904 if (len < 80 || len > 65535) {
5905 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
5906 file, linenum, args[arg+3]);
5907 err_code |= ERR_ALERT | ERR_FATAL;
5908 goto out;
5909 }
5910 logsrv->maxlen = len;
5911
5912 /* skip these two args */
5913 arg += 2;
5914 }
5915 else
5916 logsrv->maxlen = MAX_SYSLOG_LEN;
5917
5918 if (logsrv->maxlen > global.max_syslog_len) {
5919 global.max_syslog_len = logsrv->maxlen;
Dragan Dosen59cee972015-09-19 22:09:02 +02005920 logheader = realloc(logheader, global.max_syslog_len + 1);
Dragan Dosen1322d092015-09-22 16:05:32 +02005921 logheader_rfc5424 = realloc(logheader_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02005922 logline = realloc(logline, global.max_syslog_len + 1);
Dragan Dosen0b85ece2015-09-25 19:17:44 +02005923 logline_rfc5424 = realloc(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02005924 }
5925
Dragan Dosen1322d092015-09-22 16:05:32 +02005926 /* after the length, a format may be specified */
5927 if (strcmp(args[arg+2], "format") == 0) {
5928 logsrv->format = get_log_format(args[arg+3]);
5929 if (logsrv->format < 0) {
5930 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
5931 err_code |= ERR_ALERT | ERR_FATAL;
5932 goto out;
5933 }
5934
5935 /* skip these two args */
5936 arg += 2;
5937 }
5938
William Lallemanddf1425a2015-04-28 20:17:49 +02005939 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
5940 goto out;
5941
Willy Tarreau18324f52014-06-27 18:10:07 +02005942 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005943 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005944 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005945 err_code |= ERR_ALERT | ERR_FATAL;
5946 goto out;
5947
Willy Tarreaubaaee002006-06-26 02:48:02 +02005948 }
5949
William Lallemand0f99e342011-10-12 17:50:54 +02005950 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02005951 if (*(args[arg+3])) {
5952 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005953 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005954 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005955 err_code |= ERR_ALERT | ERR_FATAL;
5956 goto out;
5957
Willy Tarreaubaaee002006-06-26 02:48:02 +02005958 }
5959 }
5960
William Lallemand0f99e342011-10-12 17:50:54 +02005961 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02005962 if (*(args[arg+4])) {
5963 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01005964 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005965 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02005966 err_code |= ERR_ALERT | ERR_FATAL;
5967 goto out;
5968
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005969 }
5970 }
5971
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02005972 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005973 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005974 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005975 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005976 goto out;
5977 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005978
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005979 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005980
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005981 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005982 if (port1 != port2) {
5983 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5984 file, linenum, args[0], args[1]);
5985 err_code |= ERR_ALERT | ERR_FATAL;
5986 goto out;
5987 }
5988
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005989 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02005990 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005991 }
William Lallemand0f99e342011-10-12 17:50:54 +02005992
5993 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005994 }
5995 else {
5996 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
5997 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005998 err_code |= ERR_ALERT | ERR_FATAL;
5999 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006000 }
6001 }
6002 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006003 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006004 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01006005 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006006 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006007
Willy Tarreau977b8e42006-12-29 14:19:17 +01006008 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006009 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006010
Willy Tarreaubaaee002006-06-26 02:48:02 +02006011 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006012 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
6013 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02006014 err_code |= ERR_ALERT | ERR_FATAL;
6015 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006016 }
Willy Tarreau368480c2009-03-01 08:27:21 +01006017
6018 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01006019 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6020 free(curproxy->conn_src.iface_name);
6021 curproxy->conn_src.iface_name = NULL;
6022 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01006023
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006024 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006025 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006026 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006027 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006028 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006029 goto out;
6030 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006031
6032 proto = protocol_by_family(sk->ss_family);
6033 if (!proto || !proto->connect) {
6034 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006035 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006036 err_code |= ERR_ALERT | ERR_FATAL;
6037 goto out;
6038 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006039
6040 if (port1 != port2) {
6041 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6042 file, linenum, args[0], args[1]);
6043 err_code |= ERR_ALERT | ERR_FATAL;
6044 goto out;
6045 }
6046
Willy Tarreauef9a3602012-12-08 22:29:20 +01006047 curproxy->conn_src.source_addr = *sk;
6048 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006049
6050 cur_arg = 2;
6051 while (*(args[cur_arg])) {
6052 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau29fbe512015-08-20 19:35:14 +02006053#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006054 if (!*args[cur_arg + 1]) {
6055 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
6056 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006057 err_code |= ERR_ALERT | ERR_FATAL;
6058 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006059 }
6060
6061 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006062 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6063 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006064 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006065 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6066 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02006067 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
6068 char *name, *end;
6069
6070 name = args[cur_arg+1] + 7;
6071 while (isspace(*name))
6072 name++;
6073
6074 end = name;
6075 while (*end && !isspace(*end) && *end != ',' && *end != ')')
6076 end++;
6077
Willy Tarreauef9a3602012-12-08 22:29:20 +01006078 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6079 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
6080 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
6081 curproxy->conn_src.bind_hdr_len = end - name;
6082 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
6083 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
6084 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02006085
6086 /* now look for an occurrence number */
6087 while (isspace(*end))
6088 end++;
6089 if (*end == ',') {
6090 end++;
6091 name = end;
6092 if (*end == '-')
6093 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01006094 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02006095 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01006096 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006097 }
6098
Willy Tarreauef9a3602012-12-08 22:29:20 +01006099 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02006100 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
6101 " occurrences values smaller than %d.\n",
6102 file, linenum, MAX_HDR_HISTORY);
6103 err_code |= ERR_ALERT | ERR_FATAL;
6104 goto out;
6105 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006106 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01006107 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006108
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006109 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006110 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006111 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006112 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006113 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006114 goto out;
6115 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006116
6117 proto = protocol_by_family(sk->ss_family);
6118 if (!proto || !proto->connect) {
6119 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
6120 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006121 err_code |= ERR_ALERT | ERR_FATAL;
6122 goto out;
6123 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006124
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006125 if (port1 != port2) {
6126 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6127 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006128 err_code |= ERR_ALERT | ERR_FATAL;
6129 goto out;
6130 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006131 curproxy->conn_src.tproxy_addr = *sk;
6132 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006133 }
6134 global.last_checks |= LSTCHK_NETADM;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006135#else /* no TPROXY support */
6136 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01006137 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006138 err_code |= ERR_ALERT | ERR_FATAL;
6139 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006140#endif
6141 cur_arg += 2;
6142 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01006143 }
6144
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006145 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
6146#ifdef SO_BINDTODEVICE
6147 if (!*args[cur_arg + 1]) {
6148 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
6149 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006150 err_code |= ERR_ALERT | ERR_FATAL;
6151 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006152 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006153 free(curproxy->conn_src.iface_name);
6154 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
6155 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006156 global.last_checks |= LSTCHK_NETADM;
6157#else
6158 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
6159 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02006160 err_code |= ERR_ALERT | ERR_FATAL;
6161 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01006162#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006163 cur_arg += 2;
6164 continue;
6165 }
6166 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02006167 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006168 err_code |= ERR_ALERT | ERR_FATAL;
6169 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006170 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006171 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006172 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
6173 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
6174 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02006175 err_code |= ERR_ALERT | ERR_FATAL;
6176 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006177 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006178 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006179 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006180 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6181 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006182 err_code |= ERR_ALERT | ERR_FATAL;
6183 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006184 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006185
6186 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006187 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006188 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006189 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006190 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006191 }
6192 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006193 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006194 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006195 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006196 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006197 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006198 }
6199 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006200 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006201 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006202 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006203 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006204 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006205 }
6206 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006207 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006208 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006209 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006210 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006211 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006212 }
6213 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006214 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006215 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006216 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006217 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006218 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006219 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006220 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006221 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006222 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006223 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006224 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006225 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006226 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006227 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006228 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006229 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6230 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006231 err_code |= ERR_ALERT | ERR_FATAL;
6232 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006233 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006234
6235 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006236 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006237 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006238 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006239 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006240 }
6241 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006242 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006243 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006244 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006245 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006246 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006247 }
6248 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006249 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006250 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006251 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006252 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006253 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006254 }
6255 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006256 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006257 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006258 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006259 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006260 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006261 }
6262 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006263 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006264 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006265 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006266 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006267 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006268 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006269 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006270 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006271 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006272 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006273 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006274 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006275 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006276 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006277 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006278
Willy Tarreaubaaee002006-06-26 02:48:02 +02006279 if (curproxy == &defproxy) {
6280 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006281 err_code |= ERR_ALERT | ERR_FATAL;
6282 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006283 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006284 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006285 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006286
Willy Tarreaubaaee002006-06-26 02:48:02 +02006287 if (*(args[1]) == 0) {
6288 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006289 err_code |= ERR_ALERT | ERR_FATAL;
6290 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006291 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006292
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006293 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006294 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6295 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6296 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006297 err_code |= ERR_ALERT | ERR_FATAL;
6298 goto out;
6299 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006300 err_code |= warnif_cond_conflicts(cond,
6301 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6302 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006303 }
6304 else if (*args[2]) {
6305 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6306 file, linenum, args[0], args[2]);
6307 err_code |= ERR_ALERT | ERR_FATAL;
6308 goto out;
6309 }
6310
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006311 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006312 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006313 wl->s = strdup(args[1]);
6314 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02006315 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006316 }
6317 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006318 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006319 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6320 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006321 err_code |= ERR_ALERT | ERR_FATAL;
6322 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006323 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006324
Willy Tarreauade5ec42010-01-28 19:33:49 +01006325 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006326 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006327 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006328 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006329 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006330 }
6331 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006332 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006333 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006334 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006335 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006336 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006337 }
6338 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006339 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006340 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006341 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006342 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006343 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006344 }
6345 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006346 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006347 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6348 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006349 err_code |= ERR_ALERT | ERR_FATAL;
6350 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006351 }
6352
Willy Tarreauade5ec42010-01-28 19:33:49 +01006353 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006354 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006355 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006356 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006357 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006358 }
6359 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006360 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006361 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006362 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006363 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006364 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006365 }
6366 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006367 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006368 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006369 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006370 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006371 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006372 }
6373 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006374 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006375
Willy Tarreaubaaee002006-06-26 02:48:02 +02006376 if (curproxy == &defproxy) {
6377 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006378 err_code |= ERR_ALERT | ERR_FATAL;
6379 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006380 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006381 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006382 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006383
Willy Tarreaubaaee002006-06-26 02:48:02 +02006384 if (*(args[1]) == 0) {
6385 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006386 err_code |= ERR_ALERT | ERR_FATAL;
6387 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006388 }
6389
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006390 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006391 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6392 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6393 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006394 err_code |= ERR_ALERT | ERR_FATAL;
6395 goto out;
6396 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006397 err_code |= warnif_cond_conflicts(cond,
6398 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
6399 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006400 }
6401 else if (*args[2]) {
6402 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6403 file, linenum, args[0], args[2]);
6404 err_code |= ERR_ALERT | ERR_FATAL;
6405 goto out;
6406 }
6407
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006408 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006409 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006410 wl->s = strdup(args[1]);
6411 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006412 }
6413 else if (!strcmp(args[0], "errorloc") ||
6414 !strcmp(args[0], "errorloc302") ||
6415 !strcmp(args[0], "errorloc303")) { /* error location */
6416 int errnum, errlen;
6417 char *err;
6418
Willy Tarreau977b8e42006-12-29 14:19:17 +01006419 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006420 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006421
Willy Tarreaubaaee002006-06-26 02:48:02 +02006422 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006423 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006424 err_code |= ERR_ALERT | ERR_FATAL;
6425 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006426 }
6427
6428 errnum = atol(args[1]);
6429 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006430 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
6431 err = malloc(errlen);
6432 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006433 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006434 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
6435 err = malloc(errlen);
6436 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006437 }
6438
Willy Tarreau0f772532006-12-23 20:51:41 +01006439 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6440 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006441 chunk_destroy(&curproxy->errmsg[rc]);
6442 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01006443 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006444 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006445 }
Willy Tarreau0f772532006-12-23 20:51:41 +01006446
6447 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006448 Warning("parsing [%s:%d] : status code %d not handled by '%s', error relocation will be ignored.\n",
6449 file, linenum, errnum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006450 free(err);
6451 }
6452 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02006453 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
6454 int errnum, errlen, fd;
6455 char *err;
6456 struct stat stat;
6457
6458 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006459 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006460
6461 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006462 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006463 err_code |= ERR_ALERT | ERR_FATAL;
6464 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006465 }
6466
6467 fd = open(args[2], O_RDONLY);
6468 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
6469 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
6470 file, linenum, args[2], args[1]);
6471 if (fd >= 0)
6472 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02006473 err_code |= ERR_ALERT | ERR_FATAL;
6474 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006475 }
6476
Willy Tarreau27a674e2009-08-17 07:23:33 +02006477 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02006478 errlen = stat.st_size;
6479 } else {
6480 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02006481 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02006482 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02006483 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006484 }
6485
6486 err = malloc(errlen); /* malloc() must succeed during parsing */
6487 errnum = read(fd, err, errlen);
6488 if (errnum != errlen) {
6489 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
6490 file, linenum, args[2], args[1]);
6491 close(fd);
6492 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02006493 err_code |= ERR_ALERT | ERR_FATAL;
6494 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006495 }
6496 close(fd);
6497
6498 errnum = atol(args[1]);
6499 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6500 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006501 chunk_destroy(&curproxy->errmsg[rc]);
6502 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02006503 break;
6504 }
6505 }
6506
6507 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006508 Warning("parsing [%s:%d] : status code %d not handled by '%s', error customization will be ignored.\n",
6509 file, linenum, errnum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006510 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006511 free(err);
6512 }
6513 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006514 else if (!strcmp(args[0], "compression")) {
6515 struct comp *comp;
6516 if (curproxy->comp == NULL) {
6517 comp = calloc(1, sizeof(struct comp));
6518 curproxy->comp = comp;
6519 } else {
6520 comp = curproxy->comp;
6521 }
6522
6523 if (!strcmp(args[1], "algo")) {
6524 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01006525 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01006526
William Lallemand82fe75c2012-10-23 10:25:10 +02006527 cur_arg = 2;
6528 if (!*args[cur_arg]) {
6529 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
6530 file, linenum, args[0]);
6531 err_code |= ERR_ALERT | ERR_FATAL;
6532 goto out;
6533 }
6534 while (*(args[cur_arg])) {
6535 if (comp_append_algo(comp, args[cur_arg]) < 0) {
6536 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
6537 file, linenum, args[0], args[cur_arg]);
6538 err_code |= ERR_ALERT | ERR_FATAL;
6539 goto out;
6540 }
William Lallemand552df672012-11-07 13:21:47 +01006541 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
6542 curproxy->comp->algos->end(&ctx);
6543 } else {
6544 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
6545 file, linenum, args[0], args[cur_arg]);
6546 err_code |= ERR_ALERT | ERR_FATAL;
6547 goto out;
6548 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006549 cur_arg ++;
6550 continue;
6551 }
6552 }
Willy Tarreau70737d12012-10-27 00:34:28 +02006553 else if (!strcmp(args[1], "offload")) {
6554 comp->offload = 1;
6555 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006556 else if (!strcmp(args[1], "type")) {
6557 int cur_arg;
6558 cur_arg = 2;
6559 if (!*args[cur_arg]) {
6560 Alert("parsing [%s:%d] : '%s' expects <type>\n",
6561 file, linenum, args[0]);
6562 err_code |= ERR_ALERT | ERR_FATAL;
6563 goto out;
6564 }
6565 while (*(args[cur_arg])) {
6566 comp_append_type(comp, args[cur_arg]);
6567 cur_arg ++;
6568 continue;
6569 }
6570 }
6571 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02006572 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02006573 file, linenum, args[0]);
6574 err_code |= ERR_ALERT | ERR_FATAL;
6575 goto out;
6576 }
6577 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006578 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006579 struct cfg_kw_list *kwl;
6580 int index;
6581
6582 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6583 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6584 if (kwl->kw[index].section != CFG_LISTEN)
6585 continue;
6586 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6587 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006588 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006589 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006590 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006591 err_code |= ERR_ALERT | ERR_FATAL;
6592 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006593 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006594 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006595 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006596 err_code |= ERR_WARN;
6597 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006598 }
Willy Tarreau93893792009-07-23 13:19:11 +02006599 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006600 }
6601 }
6602 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006603
Willy Tarreau6daf3432008-01-22 16:44:08 +01006604 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006605 err_code |= ERR_ALERT | ERR_FATAL;
6606 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006607 }
Willy Tarreau93893792009-07-23 13:19:11 +02006608 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006609 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006610 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006611}
6612
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006613int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006614cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
6615{
6616#ifdef CONFIG_HAP_NS
6617 const char *err;
6618 const char *item = args[0];
6619
6620 if (!strcmp(item, "namespace_list")) {
6621 return 0;
6622 }
6623 else if (!strcmp(item, "namespace")) {
6624 size_t idx = 1;
6625 const char *current;
6626 while (*(current = args[idx++])) {
6627 err = invalid_char(current);
6628 if (err) {
6629 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6630 file, linenum, *err, item, current);
6631 return ERR_ALERT | ERR_FATAL;
6632 }
6633
6634 if (netns_store_lookup(current, strlen(current))) {
6635 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
6636 file, linenum, current);
6637 return ERR_ALERT | ERR_FATAL;
6638 }
6639 if (!netns_store_insert(current)) {
6640 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
6641 file, linenum, current);
6642 return ERR_ALERT | ERR_FATAL;
6643 }
6644 }
6645 }
6646
6647 return 0;
6648#else
6649 Alert("parsing [%s:%d]: namespace support is not compiled in.",
6650 file, linenum);
6651 return ERR_ALERT | ERR_FATAL;
6652#endif
6653}
6654
6655int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006656cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6657{
6658
6659 int err_code = 0;
6660 const char *err;
6661
6662 if (!strcmp(args[0], "userlist")) { /* new userlist */
6663 struct userlist *newul;
6664
6665 if (!*args[1]) {
6666 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6667 file, linenum, args[0]);
6668 err_code |= ERR_ALERT | ERR_FATAL;
6669 goto out;
6670 }
William Lallemand6e62fb62015-04-28 16:55:23 +02006671 if (alertif_too_many_args(1, file, linenum, args, &err_code))
6672 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006673
6674 err = invalid_char(args[1]);
6675 if (err) {
6676 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6677 file, linenum, *err, args[0], args[1]);
6678 err_code |= ERR_ALERT | ERR_FATAL;
6679 goto out;
6680 }
6681
6682 for (newul = userlist; newul; newul = newul->next)
6683 if (!strcmp(newul->name, args[1])) {
6684 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6685 file, linenum, args[1]);
6686 err_code |= ERR_WARN;
6687 goto out;
6688 }
6689
6690 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
6691 if (!newul) {
6692 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6693 err_code |= ERR_ALERT | ERR_ABORT;
6694 goto out;
6695 }
6696
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006697 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006698 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006699 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6700 err_code |= ERR_ALERT | ERR_ABORT;
6701 goto out;
6702 }
6703
6704 newul->next = userlist;
6705 userlist = newul;
6706
6707 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006708 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006709 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006710 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006711
6712 if (!*args[1]) {
6713 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6714 file, linenum, args[0]);
6715 err_code |= ERR_ALERT | ERR_FATAL;
6716 goto out;
6717 }
6718
6719 err = invalid_char(args[1]);
6720 if (err) {
6721 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6722 file, linenum, *err, args[0], args[1]);
6723 err_code |= ERR_ALERT | ERR_FATAL;
6724 goto out;
6725 }
6726
William Lallemand4ac9f542015-05-28 18:03:51 +02006727 if (!userlist)
6728 goto out;
6729
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006730 for (ag = userlist->groups; ag; ag = ag->next)
6731 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006732 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6733 file, linenum, args[1], userlist->name);
6734 err_code |= ERR_ALERT;
6735 goto out;
6736 }
6737
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006738 ag = calloc(1, sizeof(*ag));
6739 if (!ag) {
6740 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6741 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006742 goto out;
6743 }
6744
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006745 ag->name = strdup(args[1]);
6746 if (!ag) {
6747 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6748 err_code |= ERR_ALERT | ERR_ABORT;
6749 goto out;
6750 }
6751
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006752 cur_arg = 2;
6753
6754 while (*args[cur_arg]) {
6755 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006756 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006757 cur_arg += 2;
6758 continue;
6759 } else {
6760 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6761 file, linenum, args[0]);
6762 err_code |= ERR_ALERT | ERR_FATAL;
6763 goto out;
6764 }
6765 }
6766
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006767 ag->next = userlist->groups;
6768 userlist->groups = ag;
6769
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006770 } else if (!strcmp(args[0], "user")) { /* new user */
6771 struct auth_users *newuser;
6772 int cur_arg;
6773
6774 if (!*args[1]) {
6775 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6776 file, linenum, args[0]);
6777 err_code |= ERR_ALERT | ERR_FATAL;
6778 goto out;
6779 }
William Lallemand4ac9f542015-05-28 18:03:51 +02006780 if (!userlist)
6781 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006782
6783 for (newuser = userlist->users; newuser; newuser = newuser->next)
6784 if (!strcmp(newuser->user, args[1])) {
6785 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6786 file, linenum, args[1], userlist->name);
6787 err_code |= ERR_ALERT;
6788 goto out;
6789 }
6790
6791 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
6792 if (!newuser) {
6793 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6794 err_code |= ERR_ALERT | ERR_ABORT;
6795 goto out;
6796 }
6797
6798 newuser->user = strdup(args[1]);
6799
6800 newuser->next = userlist->users;
6801 userlist->users = newuser;
6802
6803 cur_arg = 2;
6804
6805 while (*args[cur_arg]) {
6806 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006807#ifdef CONFIG_HAP_CRYPT
6808 if (!crypt("", args[cur_arg + 1])) {
6809 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6810 file, linenum, newuser->user);
6811 err_code |= ERR_ALERT | ERR_FATAL;
6812 goto out;
6813 }
6814#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006815 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6816 file, linenum);
6817 err_code |= ERR_ALERT;
6818#endif
6819 newuser->pass = strdup(args[cur_arg + 1]);
6820 cur_arg += 2;
6821 continue;
6822 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6823 newuser->pass = strdup(args[cur_arg + 1]);
6824 newuser->flags |= AU_O_INSECURE;
6825 cur_arg += 2;
6826 continue;
6827 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006828 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006829 cur_arg += 2;
6830 continue;
6831 } else {
6832 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6833 file, linenum, args[0]);
6834 err_code |= ERR_ALERT | ERR_FATAL;
6835 goto out;
6836 }
6837 }
6838 } else {
6839 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6840 err_code |= ERR_ALERT | ERR_FATAL;
6841 }
6842
6843out:
6844 return err_code;
6845}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006846
6847/*
6848 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006849 * Returns the error code, 0 if OK, or any combination of :
6850 * - ERR_ABORT: must abort ASAP
6851 * - ERR_FATAL: we can continue parsing but not start the service
6852 * - ERR_WARN: a warning has been emitted
6853 * - ERR_ALERT: an alert has been emitted
6854 * Only the two first ones can stop processing, the two others are just
6855 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006856 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006857int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006858{
William Lallemand64e84512015-05-12 14:25:37 +02006859 char *thisline;
6860 int linesize = LINESIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006861 FILE *f;
6862 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02006863 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006864 struct cfg_section *cs = NULL;
6865 struct cfg_section *ics;
William Lallemand64e84512015-05-12 14:25:37 +02006866 int readbytes = 0;
6867
6868 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
William Lallemandb2f07452015-05-12 14:27:13 +02006869 Alert("parsing [%s] : out of memory.\n", file);
William Lallemand64e84512015-05-12 14:25:37 +02006870 return -1;
6871 }
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006872
6873 /* Register internal sections */
6874 if (!cfg_register_section("listen", cfg_parse_listen) ||
6875 !cfg_register_section("frontend", cfg_parse_listen) ||
6876 !cfg_register_section("backend", cfg_parse_listen) ||
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006877 !cfg_register_section("defaults", cfg_parse_listen) ||
6878 !cfg_register_section("global", cfg_parse_global) ||
6879 !cfg_register_section("userlist", cfg_parse_users) ||
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006880 !cfg_register_section("peers", cfg_parse_peers) ||
Simon Horman0d16a402015-01-30 11:22:58 +09006881 !cfg_register_section("mailers", cfg_parse_mailers) ||
Baptiste Assmann325137d2015-04-13 23:40:55 +02006882 !cfg_register_section("namespace_list", cfg_parse_netns) ||
6883 !cfg_register_section("resolvers", cfg_parse_resolvers))
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006884 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006885
Willy Tarreaubaaee002006-06-26 02:48:02 +02006886 if ((f=fopen(file,"r")) == NULL)
6887 return -1;
6888
William Lallemandb2f07452015-05-12 14:27:13 +02006889next_line:
William Lallemand64e84512015-05-12 14:25:37 +02006890 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02006891 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006892 char *end;
6893 char *args[MAX_LINE_ARGS + 1];
6894 char *line = thisline;
William Lallemandf9873ba2015-05-05 17:37:14 +02006895 int dquote = 0; /* double quote */
6896 int squote = 0; /* simple quote */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006897
Willy Tarreaubaaee002006-06-26 02:48:02 +02006898 linenum++;
6899
6900 end = line + strlen(line);
6901
William Lallemand64e84512015-05-12 14:25:37 +02006902 if (end-line == linesize-1 && *(end-1) != '\n') {
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006903 /* Check if we reached the limit and the last char is not \n.
6904 * Watch out for the last line without the terminating '\n'!
6905 */
William Lallemand64e84512015-05-12 14:25:37 +02006906 char *newline;
6907 int newlinesize = linesize * 2;
6908
6909 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
6910 if (newline == NULL) {
6911 Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
6912 file, linenum);
6913 err_code |= ERR_ALERT | ERR_FATAL;
6914 continue;
6915 }
6916
6917 readbytes = linesize - 1;
6918 linesize = newlinesize;
6919 thisline = newline;
6920 continue;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006921 }
6922
William Lallemand64e84512015-05-12 14:25:37 +02006923 readbytes = 0;
6924
Willy Tarreaubaaee002006-06-26 02:48:02 +02006925 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006926 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006927 line++;
William Lallemandf9873ba2015-05-05 17:37:14 +02006928
Willy Tarreaubaaee002006-06-26 02:48:02 +02006929 arg = 0;
6930 args[arg] = line;
6931
6932 while (*line && arg < MAX_LINE_ARGS) {
William Lallemandf9873ba2015-05-05 17:37:14 +02006933 if (*line == '"' && !squote) { /* double quote outside single quotes */
6934 if (dquote)
6935 dquote = 0;
6936 else
6937 dquote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02006938 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02006939 end--;
6940 }
6941 else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
6942 if (squote)
6943 squote = 0;
6944 else
6945 squote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02006946 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02006947 end--;
6948 }
6949 else if (*line == '\\' && !squote) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006950 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
6951 * C equivalent value. Other combinations left unchanged (eg: \1).
6952 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006953 int skip = 0;
6954 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
6955 *line = line[1];
6956 skip = 1;
6957 }
6958 else if (line[1] == 'r') {
6959 *line = '\r';
6960 skip = 1;
William Lallemandf9873ba2015-05-05 17:37:14 +02006961 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006962 else if (line[1] == 'n') {
6963 *line = '\n';
6964 skip = 1;
6965 }
6966 else if (line[1] == 't') {
6967 *line = '\t';
6968 skip = 1;
6969 }
6970 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01006971 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006972 unsigned char hex1, hex2;
6973 hex1 = toupper(line[2]) - '0';
6974 hex2 = toupper(line[3]) - '0';
6975 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
6976 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
6977 *line = (hex1<<4) + hex2;
6978 skip = 3;
6979 }
6980 else {
6981 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006982 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006983 }
William Lallemandf9873ba2015-05-05 17:37:14 +02006984 } else if (line[1] == '"') {
6985 *line = '"';
6986 skip = 1;
6987 } else if (line[1] == '\'') {
6988 *line = '\'';
6989 skip = 1;
William Lallemandb2f07452015-05-12 14:27:13 +02006990 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
6991 *line = '$';
6992 skip = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006993 }
6994 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01006995 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006996 end -= skip;
6997 }
6998 line++;
6999 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007000 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007001 /* end of string, end of loop */
7002 *line = 0;
7003 break;
7004 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007005 else if (!squote && !dquote && isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007006 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007007 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007008 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007009 line++;
7010 args[++arg] = line;
7011 }
William Lallemandb2f07452015-05-12 14:27:13 +02007012 else if (dquote && *line == '$') {
7013 /* environment variables are evaluated inside double quotes */
7014 char *var_beg;
7015 char *var_end;
7016 char save_char;
7017 char *value;
7018 int val_len;
7019 int newlinesize;
7020 int braces = 0;
7021
7022 var_beg = line + 1;
7023 var_end = var_beg;
7024
7025 if (*var_beg == '{') {
7026 var_beg++;
7027 var_end++;
7028 braces = 1;
7029 }
7030
7031 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
7032 Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
7033 err_code |= ERR_ALERT | ERR_FATAL;
7034 goto next_line; /* skip current line */
7035 }
7036
7037 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
7038 var_end++;
7039
7040 save_char = *var_end;
7041 *var_end = '\0';
7042 value = getenv(var_beg);
7043 *var_end = save_char;
7044 val_len = value ? strlen(value) : 0;
7045
7046 if (braces) {
7047 if (*var_end == '}') {
7048 var_end++;
7049 braces = 0;
7050 } else {
7051 Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
7052 err_code |= ERR_ALERT | ERR_FATAL;
7053 goto next_line; /* skip current line */
7054 }
7055 }
7056
7057 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
7058
7059 /* if not enough space in thisline */
7060 if (newlinesize > linesize) {
7061 char *newline;
7062
7063 newline = realloc(thisline, newlinesize * sizeof(*thisline));
7064 if (newline == NULL) {
7065 Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
7066 err_code |= ERR_ALERT | ERR_FATAL;
7067 goto next_line; /* slip current line */
7068 }
7069 /* recompute pointers if realloc returns a new pointer */
7070 if (newline != thisline) {
7071 int i;
7072 int diff;
7073
7074 for (i = 0; i <= arg; i++) {
7075 diff = args[i] - thisline;
7076 args[i] = newline + diff;
7077 }
7078
7079 diff = var_end - thisline;
7080 var_end = newline + diff;
7081 diff = end - thisline;
7082 end = newline + diff;
7083 diff = line - thisline;
7084 line = newline + diff;
7085 thisline = newline;
7086 }
7087 linesize = newlinesize;
7088 }
7089
7090 /* insert value inside the line */
7091 memmove(line + val_len, var_end, end - var_end + 1);
7092 memcpy(line, value, val_len);
7093 end += val_len - (var_end - line);
7094 line += val_len;
7095 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007096 else {
7097 line++;
7098 }
7099 }
William Lallemandb2f07452015-05-12 14:27:13 +02007100
William Lallemandf9873ba2015-05-05 17:37:14 +02007101 if (dquote) {
7102 Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
7103 err_code |= ERR_ALERT | ERR_FATAL;
7104 }
7105
7106 if (squote) {
7107 Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
7108 err_code |= ERR_ALERT | ERR_FATAL;
7109 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007110
7111 /* empty line */
7112 if (!**args)
7113 continue;
7114
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007115 if (*line) {
7116 /* we had to stop due to too many args.
7117 * Let's terminate the string, print the offending part then cut the
7118 * last arg.
7119 */
7120 while (*line && *line != '#' && *line != '\n' && *line != '\r')
7121 line++;
7122 *line = '\0';
7123
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01007124 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01007125 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007126 err_code |= ERR_ALERT | ERR_FATAL;
7127 args[arg] = line;
7128 }
7129
Willy Tarreau540abe42007-05-02 20:50:16 +02007130 /* zero out remaining args and ensure that at least one entry
7131 * is zeroed out.
7132 */
7133 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007134 args[arg] = line;
7135 }
7136
Willy Tarreau3842f002009-06-14 11:39:52 +02007137 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007138 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02007139 char *tmp;
7140
Willy Tarreau3842f002009-06-14 11:39:52 +02007141 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02007142 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007143 for (arg=0; *args[arg+1]; arg++)
7144 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02007145 *tmp = '\0'; // fix the next arg to \0
7146 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007147 }
Willy Tarreau3842f002009-06-14 11:39:52 +02007148 else if (!strcmp(args[0], "default")) {
7149 kwm = KWM_DEF;
7150 for (arg=0; *args[arg+1]; arg++)
7151 args[arg] = args[arg+1]; // shift args after inversion
7152 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007153
William Lallemand0f99e342011-10-12 17:50:54 +02007154 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
7155 strcmp(args[0], "log") != 0) {
7156 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02007157 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007158 }
7159
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007160 /* detect section start */
7161 list_for_each_entry(ics, &sections, list) {
7162 if (strcmp(args[0], ics->section_name) == 0) {
7163 cursection = ics->section_name;
7164 cs = ics;
7165 break;
7166 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007167 }
7168
Willy Tarreaubaaee002006-06-26 02:48:02 +02007169 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007170 if (cs)
7171 err_code |= cs->section_parser(file, linenum, args, kwm);
7172 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007173 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007174 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007175 }
Willy Tarreau058e9072009-07-20 09:30:05 +02007176
7177 if (err_code & ERR_ABORT)
7178 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007179 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01007180 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02007181 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007182 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02007183 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007184}
7185
Willy Tarreau64ab6072014-09-16 12:17:36 +02007186/* This function propagates processes from frontend <from> to backend <to> so
7187 * that it is always guaranteed that a backend pointed to by a frontend is
7188 * bound to all of its processes. After that, if the target is a "listen"
7189 * instance, the function recursively descends the target's own targets along
Willy Tarreau98d04852015-05-26 12:18:29 +02007190 * default_backend and use_backend rules. Since the bits are
Willy Tarreau64ab6072014-09-16 12:17:36 +02007191 * checked first to ensure that <to> is already bound to all processes of
7192 * <from>, there is no risk of looping and we ensure to follow the shortest
7193 * path to the destination.
7194 *
7195 * It is possible to set <to> to NULL for the first call so that the function
7196 * takes care of visiting the initial frontend in <from>.
7197 *
7198 * It is important to note that the function relies on the fact that all names
7199 * have already been resolved.
7200 */
7201void propagate_processes(struct proxy *from, struct proxy *to)
7202{
7203 struct switching_rule *rule;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007204
7205 if (to) {
7206 /* check whether we need to go down */
7207 if (from->bind_proc &&
7208 (from->bind_proc & to->bind_proc) == from->bind_proc)
7209 return;
7210
7211 if (!from->bind_proc && !to->bind_proc)
7212 return;
7213
7214 to->bind_proc = from->bind_proc ?
7215 (to->bind_proc | from->bind_proc) : 0;
7216
7217 /* now propagate down */
7218 from = to;
7219 }
7220
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01007221 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02007222 return;
7223
Willy Tarreauf6b70012014-12-18 14:00:43 +01007224 if (from->state == PR_STSTOPPED)
7225 return;
7226
Willy Tarreau64ab6072014-09-16 12:17:36 +02007227 /* default_backend */
7228 if (from->defbe.be)
7229 propagate_processes(from, from->defbe.be);
7230
7231 /* use_backend */
7232 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02007233 if (rule->dynamic)
7234 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007235 to = rule->be.backend;
7236 propagate_processes(from, to);
7237 }
Willy Tarreau64ab6072014-09-16 12:17:36 +02007238}
7239
Willy Tarreaubb925012009-07-23 13:36:36 +02007240/*
7241 * Returns the error code, 0 if OK, or any combination of :
7242 * - ERR_ABORT: must abort ASAP
7243 * - ERR_FATAL: we can continue parsing but not start the service
7244 * - ERR_WARN: a warning has been emitted
7245 * - ERR_ALERT: an alert has been emitted
7246 * Only the two first ones can stop processing, the two others are just
7247 * indicators.
7248 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007249int check_config_validity()
7250{
7251 int cfgerr = 0;
7252 struct proxy *curproxy = NULL;
7253 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02007254 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007255 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007256 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007257
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007258 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007259 /*
7260 * Now, check for the integrity of all that we have collected.
7261 */
7262
7263 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02007264 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007265
Willy Tarreau193b8c62012-11-22 00:17:38 +01007266 if (!global.tune.max_http_hdr)
7267 global.tune.max_http_hdr = MAX_HTTP_HDR;
7268
7269 if (!global.tune.cookie_len)
7270 global.tune.cookie_len = CAPTURE_LEN;
7271
7272 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
7273
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007274 /* Post initialisation of the users and groups lists. */
7275 err_code = userlist_postinit();
7276 if (err_code != ERR_NONE)
7277 goto out;
7278
Willy Tarreau55bc0f82009-03-15 14:51:53 +01007279 /* first, we will invert the proxy list order */
7280 curproxy = NULL;
7281 while (proxy) {
7282 struct proxy *next;
7283
7284 next = proxy->next;
7285 proxy->next = curproxy;
7286 curproxy = proxy;
7287 if (!next)
7288 break;
7289 proxy = next;
7290 }
7291
Willy Tarreau419ead82014-09-16 13:41:21 +02007292 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007293 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007294 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01007295 struct sticking_rule *mrule;
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007296 struct act_rule *trule;
7297 struct act_rule *hrqrule;
Dragan Dosen1322d092015-09-22 16:05:32 +02007298 struct logsrv *tmplogsrv;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007299 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01007300 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007301
Willy Tarreau050536d2012-10-04 08:47:34 +02007302 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007303 /* proxy ID not set, use automatic numbering with first
7304 * spare entry starting with next_pxid.
7305 */
7306 next_pxid = get_next_id(&used_proxy_id, next_pxid);
7307 curproxy->conf.id.key = curproxy->uuid = next_pxid;
7308 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007309 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007310 next_pxid++;
7311
Willy Tarreau55ea7572007-06-17 19:56:27 +02007312
Willy Tarreaubaaee002006-06-26 02:48:02 +02007313 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02007314 /* ensure we don't keep listeners uselessly bound */
7315 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02007316 free((void *)curproxy->table.peers.name);
7317 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007318 continue;
7319 }
7320
Willy Tarreau102df612014-05-07 23:56:38 +02007321 /* Check multi-process mode compatibility for the current proxy */
7322
7323 if (curproxy->bind_proc) {
7324 /* an explicit bind-process was specified, let's check how many
7325 * processes remain.
7326 */
David Carliere6c39412015-07-02 07:00:17 +00007327 nbproc = my_popcountl(curproxy->bind_proc);
Willy Tarreau102df612014-05-07 23:56:38 +02007328
7329 curproxy->bind_proc &= nbits(global.nbproc);
7330 if (!curproxy->bind_proc && nbproc == 1) {
7331 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);
7332 curproxy->bind_proc = 1;
7333 }
7334 else if (!curproxy->bind_proc && nbproc > 1) {
7335 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);
7336 curproxy->bind_proc = 0;
7337 }
7338 }
7339
Willy Tarreau3d209582014-05-09 17:06:11 +02007340 /* check and reduce the bind-proc of each listener */
7341 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7342 unsigned long mask;
7343
7344 if (!bind_conf->bind_proc)
7345 continue;
7346
7347 mask = nbits(global.nbproc);
7348 if (curproxy->bind_proc)
7349 mask &= curproxy->bind_proc;
7350 /* mask cannot be null here thanks to the previous checks */
7351
David Carliere6c39412015-07-02 07:00:17 +00007352 nbproc = my_popcountl(bind_conf->bind_proc);
Willy Tarreau3d209582014-05-09 17:06:11 +02007353 bind_conf->bind_proc &= mask;
7354
7355 if (!bind_conf->bind_proc && nbproc == 1) {
7356 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",
7357 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7358 bind_conf->bind_proc = mask & ~(mask - 1);
7359 }
7360 else if (!bind_conf->bind_proc && nbproc > 1) {
7361 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",
7362 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7363 bind_conf->bind_proc = 0;
7364 }
7365 }
7366
Willy Tarreauff01a212009-03-15 13:46:16 +01007367 switch (curproxy->mode) {
7368 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007369 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007370 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007371 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
7372 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007373 cfgerr++;
7374 }
7375
7376 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007377 Warning("config : servers will be ignored for %s '%s'.\n",
7378 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007379 break;
7380
7381 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007382 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007383 break;
7384
7385 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01007386 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01007387 break;
7388 }
7389
Willy Tarreauf3934b82015-08-11 11:36:45 +02007390 if ((curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->conf.listeners)) {
7391 Warning("config : %s '%s' has no 'bind' directive. Please declare it as a backend if this was intended.\n",
7392 proxy_type_str(curproxy), curproxy->id);
7393 err_code |= ERR_WARN;
7394 }
7395
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007396 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007397 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007398 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007399 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
7400 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007401 cfgerr++;
7402 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007403#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007404 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007405 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
7406 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007407 cfgerr++;
7408 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007409#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02007410 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007411 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
7412 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007413 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007414 }
7415 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02007416 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007417 /* If no LB algo is set in a backend, and we're not in
7418 * transparent mode, dispatch mode nor proxy mode, we
7419 * want to use balance roundrobin by default.
7420 */
7421 curproxy->lbprm.algo &= ~BE_LB_ALGO;
7422 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007423 }
7424 }
Willy Tarreau193cf932007-09-17 10:17:23 +02007425
Willy Tarreau1620ec32011-08-06 17:05:02 +02007426 if (curproxy->options & PR_O_DISPATCH)
7427 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
7428 else if (curproxy->options & PR_O_HTTP_PROXY)
7429 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
7430 else if (curproxy->options & PR_O_TRANSP)
7431 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01007432
Willy Tarreau1620ec32011-08-06 17:05:02 +02007433 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
7434 if (curproxy->options & PR_O_DISABLE404) {
7435 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7436 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
7437 err_code |= ERR_WARN;
7438 curproxy->options &= ~PR_O_DISABLE404;
7439 }
7440 if (curproxy->options2 & PR_O2_CHK_SNDST) {
7441 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7442 "send-state", proxy_type_str(curproxy), curproxy->id);
7443 err_code |= ERR_WARN;
7444 curproxy->options &= ~PR_O2_CHK_SNDST;
7445 }
Willy Tarreauef781042010-01-27 11:53:01 +01007446 }
7447
Simon Horman98637e52014-06-20 12:30:16 +09007448 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
7449 if (!global.external_check) {
7450 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
7451 curproxy->id, "option external-check");
7452 cfgerr++;
7453 }
7454 if (!curproxy->check_command) {
7455 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
7456 curproxy->id, "option external-check");
7457 cfgerr++;
7458 }
7459 }
7460
Simon Horman64e34162015-02-06 11:11:57 +09007461 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007462 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
7463 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Pieter Baauw8669e972015-08-17 00:45:05 +02007464 "'email-alert from', 'email-alert level' 'email-alert mailers', "
7465 "'email-alert myhostname', or 'email-alert to' "
7466 "requires each of 'email-alert from', 'email-alert mailers' and 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007467 "to be present).\n",
7468 proxy_type_str(curproxy), curproxy->id);
7469 err_code |= ERR_WARN;
7470 free_email_alert(curproxy);
7471 }
7472 if (!curproxy->email_alert.myhostname)
Cyril Bontée22bfd62015-12-04 03:07:07 +01007473 curproxy->email_alert.myhostname = strdup(hostname);
Simon Horman9dc49962015-01-30 11:22:59 +09007474 }
7475
Simon Horman98637e52014-06-20 12:30:16 +09007476 if (curproxy->check_command) {
7477 int clear = 0;
7478 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7479 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7480 "external-check command", proxy_type_str(curproxy), curproxy->id);
7481 err_code |= ERR_WARN;
7482 clear = 1;
7483 }
7484 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
Ben Cabot49795eb2015-09-16 12:07:51 +01007485 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-check path' is not set.\n",
Simon Horman98637e52014-06-20 12:30:16 +09007486 curproxy->id, "external-check command");
7487 cfgerr++;
7488 }
7489 if (clear) {
7490 free(curproxy->check_command);
7491 curproxy->check_command = NULL;
7492 }
7493 }
7494
7495 if (curproxy->check_path) {
7496 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7497 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7498 "external-check path", proxy_type_str(curproxy), curproxy->id);
7499 err_code |= ERR_WARN;
7500 free(curproxy->check_path);
7501 curproxy->check_path = NULL;
7502 }
7503 }
7504
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007505 /* if a default backend was specified, let's find it */
7506 if (curproxy->defbe.name) {
7507 struct proxy *target;
7508
Willy Tarreauafb39922015-05-26 12:04:09 +02007509 target = proxy_be_by_name(curproxy->defbe.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007510 if (!target) {
7511 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
7512 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007513 cfgerr++;
7514 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007515 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
7516 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02007517 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007518 } else if (target->mode != curproxy->mode &&
7519 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7520
7521 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) as its default backend (see 'mode').\n",
7522 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7523 curproxy->conf.file, curproxy->conf.line,
7524 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7525 target->conf.file, target->conf.line);
7526 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007527 } else {
7528 free(curproxy->defbe.name);
7529 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01007530
7531 /* Emit a warning if this proxy also has some servers */
7532 if (curproxy->srv) {
7533 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
7534 curproxy->id);
7535 err_code |= ERR_WARN;
7536 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007537 }
7538 }
7539
Willy Tarreau55ea7572007-06-17 19:56:27 +02007540 /* find the target proxy for 'use_backend' rules */
7541 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007542 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007543 struct logformat_node *node;
7544 char *pxname;
7545
7546 /* Try to parse the string as a log format expression. If the result
7547 * of the parsing is only one entry containing a simple string, then
7548 * it's a standard string corresponding to a static rule, thus the
7549 * parsing is cancelled and be.name is restored to be resolved.
7550 */
7551 pxname = rule->be.name;
7552 LIST_INIT(&rule->be.expr);
7553 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
7554 curproxy->conf.args.file, curproxy->conf.args.line);
7555 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
7556
7557 if (!LIST_ISEMPTY(&rule->be.expr)) {
7558 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
7559 rule->dynamic = 1;
7560 free(pxname);
7561 continue;
7562 }
7563 /* simple string: free the expression and fall back to static rule */
7564 free(node->arg);
7565 free(node);
7566 }
7567
7568 rule->dynamic = 0;
7569 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007570
Willy Tarreauafb39922015-05-26 12:04:09 +02007571 target = proxy_be_by_name(rule->be.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007572 if (!target) {
7573 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
7574 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007575 cfgerr++;
7576 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007577 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
7578 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007579 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007580 } else if (target->mode != curproxy->mode &&
7581 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7582
7583 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) in a 'use_backend' rule (see 'mode').\n",
7584 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7585 curproxy->conf.file, curproxy->conf.line,
7586 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7587 target->conf.file, target->conf.line);
7588 cfgerr++;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007589 } else {
7590 free((void *)rule->be.name);
7591 rule->be.backend = target;
7592 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007593 }
7594
Willy Tarreau64ab6072014-09-16 12:17:36 +02007595 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007596 list_for_each_entry(srule, &curproxy->server_rules, list) {
7597 struct server *target = findserver(curproxy, srule->srv.name);
7598
7599 if (!target) {
7600 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7601 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7602 cfgerr++;
7603 continue;
7604 }
7605 free((void *)srule->srv.name);
7606 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007607 }
7608
Emeric Brunb982a3d2010-01-04 15:45:53 +01007609 /* find the target table for 'stick' rules */
7610 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7611 struct proxy *target;
7612
Emeric Brun1d33b292010-01-04 15:47:17 +01007613 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7614 if (mrule->flags & STK_IS_STORE)
7615 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7616
Emeric Brunb982a3d2010-01-04 15:45:53 +01007617 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007618 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007619 else
7620 target = curproxy;
7621
7622 if (!target) {
7623 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7624 curproxy->id, mrule->table.name);
7625 cfgerr++;
7626 }
7627 else if (target->table.size == 0) {
7628 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7629 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7630 cfgerr++;
7631 }
Willy Tarreau12785782012-04-27 21:37:17 +02007632 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7633 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007634 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7635 cfgerr++;
7636 }
7637 else {
7638 free((void *)mrule->table.name);
7639 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007640 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007641 }
7642 }
7643
7644 /* find the target table for 'store response' rules */
7645 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7646 struct proxy *target;
7647
Emeric Brun1d33b292010-01-04 15:47:17 +01007648 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7649
Emeric Brunb982a3d2010-01-04 15:45:53 +01007650 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007651 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007652 else
7653 target = curproxy;
7654
7655 if (!target) {
7656 Alert("Proxy '%s': unable to find store table '%s'.\n",
7657 curproxy->id, mrule->table.name);
7658 cfgerr++;
7659 }
7660 else if (target->table.size == 0) {
7661 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7662 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7663 cfgerr++;
7664 }
Willy Tarreau12785782012-04-27 21:37:17 +02007665 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7666 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007667 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7668 cfgerr++;
7669 }
7670 else {
7671 free((void *)mrule->table.name);
7672 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007673 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007674 }
7675 }
7676
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007677 /* find the target table for 'tcp-request' layer 4 rules */
7678 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
7679 struct proxy *target;
7680
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007681 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007682 continue;
7683
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007684 if (trule->arg.trk_ctr.table.n)
7685 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007686 else
7687 target = curproxy;
7688
7689 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007690 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007691 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007692 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007693 cfgerr++;
7694 }
7695 else if (target->table.size == 0) {
7696 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007697 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007698 cfgerr++;
7699 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007700 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007701 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007702 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007703 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007704 cfgerr++;
7705 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007706 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007707 free(trule->arg.trk_ctr.table.n);
7708 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007709 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007710 * to pass a list of counters to track and allocate them right here using
7711 * stktable_alloc_data_type().
7712 */
7713 }
7714 }
7715
Willy Tarreaud1f96522010-08-03 19:34:32 +02007716 /* find the target table for 'tcp-request' layer 6 rules */
7717 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7718 struct proxy *target;
7719
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007720 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02007721 continue;
7722
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007723 if (trule->arg.trk_ctr.table.n)
7724 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007725 else
7726 target = curproxy;
7727
7728 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007729 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007730 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007731 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02007732 cfgerr++;
7733 }
7734 else if (target->table.size == 0) {
7735 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007736 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007737 cfgerr++;
7738 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007739 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007740 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007741 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007742 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007743 cfgerr++;
7744 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02007745 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007746 free(trule->arg.trk_ctr.table.n);
7747 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007748 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02007749 * to pass a list of counters to track and allocate them right here using
7750 * stktable_alloc_data_type().
7751 */
7752 }
7753 }
7754
Baptiste Assmanne9544932015-11-03 23:31:35 +01007755 /* parse http-request capture rules to ensure id really exists */
7756 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7757 if (hrqrule->action != ACT_CUSTOM ||
7758 hrqrule->action_ptr != http_action_req_capture_by_id)
7759 continue;
7760
7761 if (hrqrule->arg.capid.idx >= curproxy->nb_req_cap) {
7762 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-request capture rule.\n",
7763 curproxy->id, hrqrule->arg.capid.idx);
7764 cfgerr++;
7765 }
7766 }
7767
7768 /* parse http-response capture rules to ensure id really exists */
7769 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
7770 if (hrqrule->action != ACT_CUSTOM ||
7771 hrqrule->action_ptr != http_action_res_capture_by_id)
7772 continue;
7773
7774 if (hrqrule->arg.capid.idx >= curproxy->nb_rsp_cap) {
7775 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-response capture rule.\n",
7776 curproxy->id, hrqrule->arg.capid.idx);
7777 cfgerr++;
7778 }
7779 }
7780
Willy Tarreau09448f72014-06-25 18:12:15 +02007781 /* find the target table for 'http-request' layer 7 rules */
7782 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7783 struct proxy *target;
7784
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007785 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau09448f72014-06-25 18:12:15 +02007786 continue;
7787
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007788 if (hrqrule->arg.trk_ctr.table.n)
7789 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
Willy Tarreau09448f72014-06-25 18:12:15 +02007790 else
7791 target = curproxy;
7792
7793 if (!target) {
7794 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007795 curproxy->id, hrqrule->arg.trk_ctr.table.n,
Willy Tarreau09448f72014-06-25 18:12:15 +02007796 http_req_trk_idx(hrqrule->action));
7797 cfgerr++;
7798 }
7799 else if (target->table.size == 0) {
7800 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007801 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau09448f72014-06-25 18:12:15 +02007802 cfgerr++;
7803 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007804 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau09448f72014-06-25 18:12:15 +02007805 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007806 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau09448f72014-06-25 18:12:15 +02007807 http_req_trk_idx(hrqrule->action));
7808 cfgerr++;
7809 }
7810 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007811 free(hrqrule->arg.trk_ctr.table.n);
7812 hrqrule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau09448f72014-06-25 18:12:15 +02007813 /* Note: if we decide to enhance the track-sc syntax, we may be able
7814 * to pass a list of counters to track and allocate them right here using
7815 * stktable_alloc_data_type().
7816 */
7817 }
7818 }
7819
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02007820 /* move any "block" rules at the beginning of the http-request rules */
7821 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
7822 /* insert block_rules into http_req_rules at the beginning */
7823 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
7824 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
7825 curproxy->block_rules.n->p = &curproxy->http_req_rules;
7826 curproxy->http_req_rules.n = curproxy->block_rules.n;
7827 LIST_INIT(&curproxy->block_rules);
7828 }
7829
Emeric Brun32da3c42010-09-23 18:39:19 +02007830 if (curproxy->table.peers.name) {
7831 struct peers *curpeers = peers;
7832
7833 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
7834 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
7835 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01007836 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02007837 break;
7838 }
7839 }
7840
7841 if (!curpeers) {
7842 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
7843 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007844 free((void *)curproxy->table.peers.name);
7845 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007846 cfgerr++;
7847 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02007848 else if (curpeers->state == PR_STSTOPPED) {
7849 /* silently disable this peers section */
7850 curproxy->table.peers.p = NULL;
7851 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007852 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02007853 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
7854 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007855 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007856 cfgerr++;
7857 }
7858 }
7859
Simon Horman9dc49962015-01-30 11:22:59 +09007860
7861 if (curproxy->email_alert.mailers.name) {
7862 struct mailers *curmailers = mailers;
7863
7864 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
7865 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
7866 free(curproxy->email_alert.mailers.name);
7867 curproxy->email_alert.mailers.m = curmailers;
7868 curmailers->users++;
7869 break;
7870 }
7871 }
7872
7873 if (!curmailers) {
7874 Alert("Proxy '%s': unable to find mailers '%s'.\n",
7875 curproxy->id, curproxy->email_alert.mailers.name);
7876 free_email_alert(curproxy);
7877 cfgerr++;
7878 }
7879 }
7880
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007881 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01007882 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007883 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
7884 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
7885 "proxy", curproxy->id);
7886 cfgerr++;
7887 goto out_uri_auth_compat;
7888 }
7889
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007890 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007891 const char *uri_auth_compat_req[10];
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007892 struct act_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01007893 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007894
Willy Tarreau95fa4692010-02-01 13:05:50 +01007895 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
7896 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007897
7898 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007899 uri_auth_compat_req[i++] = "realm";
7900 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
7901 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007902
Willy Tarreau95fa4692010-02-01 13:05:50 +01007903 uri_auth_compat_req[i++] = "unless";
7904 uri_auth_compat_req[i++] = "{";
7905 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
7906 uri_auth_compat_req[i++] = "}";
7907 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007908
Willy Tarreauff011f22011-01-06 17:51:27 +01007909 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
7910 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007911 cfgerr++;
7912 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007913 }
7914
Willy Tarreauff011f22011-01-06 17:51:27 +01007915 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01007916
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007917 if (curproxy->uri_auth->auth_realm) {
7918 free(curproxy->uri_auth->auth_realm);
7919 curproxy->uri_auth->auth_realm = NULL;
7920 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007921
7922 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007923 }
7924out_uri_auth_compat:
7925
Dragan Dosen43885c72015-10-01 13:18:13 +02007926 /* check whether we have a log server that uses RFC5424 log format */
Dragan Dosen1322d092015-09-22 16:05:32 +02007927 list_for_each_entry(tmplogsrv, &curproxy->logsrvs, list) {
Dragan Dosen43885c72015-10-01 13:18:13 +02007928 if (tmplogsrv->format == LOG_FORMAT_RFC5424) {
7929 if (!curproxy->conf.logformat_sd_string) {
7930 /* set the default logformat_sd_string */
7931 curproxy->conf.logformat_sd_string = default_rfc5424_sd_log_format;
7932 }
Dragan Dosen1322d092015-09-22 16:05:32 +02007933 break;
Dragan Dosen1322d092015-09-22 16:05:32 +02007934 }
Dragan Dosen1322d092015-09-22 16:05:32 +02007935 }
Dragan Dosen68d2e3a2015-09-19 22:35:44 +02007936
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007937 /* compile the log format */
7938 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02007939 if (curproxy->conf.logformat_string != default_http_log_format &&
7940 curproxy->conf.logformat_string != default_tcp_log_format &&
7941 curproxy->conf.logformat_string != clf_http_log_format)
7942 free(curproxy->conf.logformat_string);
7943 curproxy->conf.logformat_string = NULL;
7944 free(curproxy->conf.lfs_file);
7945 curproxy->conf.lfs_file = NULL;
7946 curproxy->conf.lfs_line = 0;
Dragan Dosen0b85ece2015-09-25 19:17:44 +02007947
7948 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
7949 free(curproxy->conf.logformat_sd_string);
7950 curproxy->conf.logformat_sd_string = NULL;
7951 free(curproxy->conf.lfsd_file);
7952 curproxy->conf.lfsd_file = NULL;
7953 curproxy->conf.lfsd_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007954 }
7955
Willy Tarreau62a61232013-04-12 18:13:46 +02007956 if (curproxy->conf.logformat_string) {
7957 curproxy->conf.args.ctx = ARGC_LOG;
7958 curproxy->conf.args.file = curproxy->conf.lfs_file;
7959 curproxy->conf.args.line = curproxy->conf.lfs_line;
7960 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007961 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007962 curproxy->conf.args.file = NULL;
7963 curproxy->conf.args.line = 0;
7964 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007965
Dragan Dosen0b85ece2015-09-25 19:17:44 +02007966 if (curproxy->conf.logformat_sd_string) {
7967 curproxy->conf.args.ctx = ARGC_LOGSD;
7968 curproxy->conf.args.file = curproxy->conf.lfsd_file;
7969 curproxy->conf.args.line = curproxy->conf.lfsd_line;
7970 parse_logformat_string(curproxy->conf.logformat_sd_string, curproxy, &curproxy->logformat_sd, LOG_OPT_MANDATORY,
7971 SMP_VAL_FE_LOG_END, curproxy->conf.lfsd_file, curproxy->conf.lfsd_line);
7972 add_to_logformat_list(NULL, NULL, LF_SEPARATOR, &curproxy->logformat_sd);
7973 curproxy->conf.args.file = NULL;
7974 curproxy->conf.args.line = 0;
7975 }
7976
Willy Tarreau62a61232013-04-12 18:13:46 +02007977 if (curproxy->conf.uniqueid_format_string) {
7978 curproxy->conf.args.ctx = ARGC_UIF;
7979 curproxy->conf.args.file = curproxy->conf.uif_file;
7980 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01007981 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Godbachd9722032014-12-18 15:44:58 +08007982 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007983 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007984 curproxy->conf.args.file = NULL;
7985 curproxy->conf.args.line = 0;
7986 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007987
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007988 /* only now we can check if some args remain unresolved.
7989 * This must be done after the users and groups resolution.
7990 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007991 cfgerr += smp_resolve_args(curproxy);
7992 if (!cfgerr)
7993 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01007994
Willy Tarreau2738a142006-07-08 17:28:09 +02007995 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007996 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02007997 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02007998 (!curproxy->timeout.connect ||
7999 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008000 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02008001 " | While not properly invalid, you will certainly encounter various problems\n"
8002 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01008003 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008004 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008005 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02008006 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02008007
Willy Tarreau1fa31262007-12-03 00:36:16 +01008008 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
8009 * We must still support older configurations, so let's find out whether those
8010 * parameters have been set or must be copied from contimeouts.
8011 */
8012 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008013 if (!curproxy->timeout.tarpit ||
8014 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008015 /* tarpit timeout not set. We search in the following order:
8016 * default.tarpit, curr.connect, default.connect.
8017 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008018 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008019 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008020 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008021 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008022 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008023 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008024 }
8025 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008026 (!curproxy->timeout.queue ||
8027 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008028 /* queue timeout not set. We search in the following order:
8029 * default.queue, curr.connect, default.connect.
8030 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008031 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008032 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008033 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008034 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008035 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008036 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008037 }
8038 }
8039
Willy Tarreau1620ec32011-08-06 17:05:02 +02008040 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01008041 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
8042 curproxy->check_req = (char *)malloc(curproxy->check_len);
8043 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02008044 }
8045
Willy Tarreau215663d2014-06-13 18:30:23 +02008046 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
8047 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
8048 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
8049 proxy_type_str(curproxy), curproxy->id);
8050 err_code |= ERR_WARN;
8051 }
8052
Willy Tarreau193b8c62012-11-22 00:17:38 +01008053 /* ensure that cookie capture length is not too large */
8054 if (curproxy->capture_len >= global.tune.cookie_len) {
8055 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
8056 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
8057 err_code |= ERR_WARN;
8058 curproxy->capture_len = global.tune.cookie_len - 1;
8059 }
8060
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008061 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01008062 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008063 curproxy->req_cap_pool = create_pool("ptrcap",
8064 curproxy->nb_req_cap * sizeof(char *),
8065 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008066 }
8067
8068 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008069 curproxy->rsp_cap_pool = create_pool("ptrcap",
8070 curproxy->nb_rsp_cap * sizeof(char *),
8071 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008072 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008073
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02008074 switch (curproxy->load_server_state_from_file) {
8075 case PR_SRV_STATE_FILE_UNSPEC:
8076 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
8077 break;
8078 case PR_SRV_STATE_FILE_GLOBAL:
8079 if (!global.server_state_file) {
8080 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",
8081 curproxy->id);
8082 err_code |= ERR_WARN;
8083 }
8084 break;
8085 }
8086
Willy Tarreaubaaee002006-06-26 02:48:02 +02008087 /* first, we will invert the servers list order */
8088 newsrv = NULL;
8089 while (curproxy->srv) {
8090 struct server *next;
8091
8092 next = curproxy->srv->next;
8093 curproxy->srv->next = newsrv;
8094 newsrv = curproxy->srv;
8095 if (!next)
8096 break;
8097 curproxy->srv = next;
8098 }
8099
Willy Tarreau17edc812014-01-03 12:14:34 +01008100 /* Check that no server name conflicts. This causes trouble in the stats.
8101 * We only emit a warning for the first conflict affecting each server,
8102 * in order to avoid combinatory explosion if all servers have the same
8103 * name. We do that only for servers which do not have an explicit ID,
8104 * because these IDs were made also for distinguishing them and we don't
8105 * want to annoy people who correctly manage them.
8106 */
8107 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
8108 struct server *other_srv;
8109
8110 if (newsrv->puid)
8111 continue;
8112
8113 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
8114 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
8115 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
8116 newsrv->conf.file, newsrv->conf.line,
8117 proxy_type_str(curproxy), curproxy->id,
8118 newsrv->id, other_srv->conf.line);
8119 break;
8120 }
8121 }
8122 }
8123
Willy Tarreaudd701652010-05-25 23:03:02 +02008124 /* assign automatic UIDs to servers which don't have one yet */
8125 next_id = 1;
8126 newsrv = curproxy->srv;
8127 while (newsrv != NULL) {
8128 if (!newsrv->puid) {
8129 /* server ID not set, use automatic numbering with first
8130 * spare entry starting with next_svid.
8131 */
8132 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
8133 newsrv->conf.id.key = newsrv->puid = next_id;
8134 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
8135 }
8136 next_id++;
8137 newsrv = newsrv->next;
8138 }
8139
Willy Tarreau20697042007-11-15 23:26:18 +01008140 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01008141 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02008142
Willy Tarreau62c3be22012-01-20 13:12:32 +01008143 /*
8144 * If this server supports a maxconn parameter, it needs a dedicated
8145 * tasks to fill the emptied slots when a connection leaves.
8146 * Also, resolve deferred tracking dependency if needed.
8147 */
8148 newsrv = curproxy->srv;
8149 while (newsrv != NULL) {
8150 if (newsrv->minconn > newsrv->maxconn) {
8151 /* Only 'minconn' was specified, or it was higher than or equal
8152 * to 'maxconn'. Let's turn this into maxconn and clean it, as
8153 * this will avoid further useless expensive computations.
8154 */
8155 newsrv->maxconn = newsrv->minconn;
8156 } else if (newsrv->maxconn && !newsrv->minconn) {
8157 /* minconn was not specified, so we set it to maxconn */
8158 newsrv->minconn = newsrv->maxconn;
8159 }
8160
Emeric Brun01f8e2f2012-05-18 16:02:00 +02008161#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02008162 if (newsrv->use_ssl || newsrv->check.use_ssl)
8163 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02008164#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02008165
Willy Tarreau2f075e92013-12-03 11:11:34 +01008166 /* set the check type on the server */
8167 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
8168
Willy Tarreau62c3be22012-01-20 13:12:32 +01008169 if (newsrv->trackit) {
8170 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02008171 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008172 char *pname, *sname;
8173
8174 pname = newsrv->trackit;
8175 sname = strrchr(pname, '/');
8176
8177 if (sname)
8178 *sname++ = '\0';
8179 else {
8180 sname = pname;
8181 pname = NULL;
8182 }
8183
8184 if (pname) {
Willy Tarreau9e0bb102015-05-26 11:24:42 +02008185 px = proxy_be_by_name(pname);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008186 if (!px) {
8187 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
8188 proxy_type_str(curproxy), curproxy->id,
8189 newsrv->id, pname);
8190 cfgerr++;
8191 goto next_srv;
8192 }
8193 } else
8194 px = curproxy;
8195
8196 srv = findserver(px, sname);
8197 if (!srv) {
8198 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
8199 proxy_type_str(curproxy), curproxy->id,
8200 newsrv->id, sname);
8201 cfgerr++;
8202 goto next_srv;
8203 }
8204
Willy Tarreau32091232014-05-16 13:52:00 +02008205 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
8206 !(srv->agent.state & CHK_ST_CONFIGURED) &&
8207 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01008208 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02008209 "tracking as it does not have any check nor agent enabled.\n",
8210 proxy_type_str(curproxy), curproxy->id,
8211 newsrv->id, px->id, srv->id);
8212 cfgerr++;
8213 goto next_srv;
8214 }
8215
8216 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
8217
8218 if (loop) {
8219 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
8220 "belongs to a tracking chain looping back to %s/%s.\n",
8221 proxy_type_str(curproxy), curproxy->id,
8222 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008223 cfgerr++;
8224 goto next_srv;
8225 }
8226
8227 if (curproxy != px &&
8228 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
8229 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
8230 "tracking: disable-on-404 option inconsistency.\n",
8231 proxy_type_str(curproxy), curproxy->id,
8232 newsrv->id, px->id, srv->id);
8233 cfgerr++;
8234 goto next_srv;
8235 }
8236
8237 /* if the other server is forced disabled, we have to do the same here */
Willy Tarreau20125212014-05-13 19:44:56 +02008238 if (srv->admin & SRV_ADMF_MAINT) {
Willy Tarreaua0066dd2014-05-16 11:25:16 +02008239 newsrv->admin |= SRV_ADMF_IMAINT;
Willy Tarreau892337c2014-05-13 23:41:20 +02008240 newsrv->state = SRV_ST_STOPPED;
Simon Horman125d0992013-02-24 17:23:38 +09008241 newsrv->check.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008242 }
8243
8244 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01008245 newsrv->tracknext = srv->trackers;
8246 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008247
8248 free(newsrv->trackit);
8249 newsrv->trackit = NULL;
8250 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008251
8252 /*
8253 * resolve server's resolvers name and update the resolvers pointer
8254 * accordingly
8255 */
8256 if (newsrv->resolvers_id) {
8257 struct dns_resolvers *curr_resolvers;
8258 int found;
8259
8260 found = 0;
8261 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
8262 if (!strcmp(curr_resolvers->id, newsrv->resolvers_id)) {
8263 found = 1;
8264 break;
8265 }
8266 }
8267
8268 if (!found) {
8269 Alert("config : %s '%s', server '%s': unable to find required resolvers '%s'\n",
8270 proxy_type_str(curproxy), curproxy->id,
8271 newsrv->id, newsrv->resolvers_id);
8272 cfgerr++;
8273 } else {
8274 free(newsrv->resolvers_id);
8275 newsrv->resolvers_id = NULL;
8276 if (newsrv->resolution)
8277 newsrv->resolution->resolvers = curr_resolvers;
8278 }
8279 }
8280 else {
8281 /* if no resolvers section associated to this server
8282 * we can clean up the associated resolution structure
8283 */
8284 if (newsrv->resolution) {
8285 free(newsrv->resolution->hostname_dn);
8286 newsrv->resolution->hostname_dn = NULL;
8287 free(newsrv->resolution);
8288 newsrv->resolution = NULL;
8289 }
8290 }
8291
Willy Tarreau62c3be22012-01-20 13:12:32 +01008292 next_srv:
8293 newsrv = newsrv->next;
8294 }
8295
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008296 /* We have to initialize the server lookup mechanism depending
8297 * on what LB algorithm was choosen.
8298 */
8299
8300 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
8301 switch (curproxy->lbprm.algo & BE_LB_KIND) {
8302 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02008303 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
8304 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8305 init_server_map(curproxy);
8306 } else {
8307 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
8308 fwrr_init_server_groups(curproxy);
8309 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008310 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008311
Willy Tarreau3ebb1162012-02-13 16:57:44 +01008312 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01008313 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
8314 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
8315 fwlc_init_server_tree(curproxy);
8316 } else {
8317 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
8318 fas_init_server_tree(curproxy);
8319 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008320 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008321
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008322 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008323 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
8324 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
8325 chash_init_server_tree(curproxy);
8326 } else {
8327 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8328 init_server_map(curproxy);
8329 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008330 break;
8331 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02008332
8333 if (curproxy->options & PR_O_LOGASAP)
8334 curproxy->to_log &= ~LW_BYTES;
8335
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008336 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008337 (curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->logsrvs) &&
8338 (!LIST_ISEMPTY(&curproxy->logformat) || !LIST_ISEMPTY(&curproxy->logformat_sd))) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008339 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
8340 proxy_type_str(curproxy), curproxy->id);
8341 err_code |= ERR_WARN;
8342 }
8343
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008344 if (curproxy->mode != PR_MODE_HTTP) {
8345 int optnum;
8346
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008347 if (curproxy->uri_auth) {
8348 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
8349 proxy_type_str(curproxy), curproxy->id);
8350 err_code |= ERR_WARN;
8351 curproxy->uri_auth = NULL;
8352 }
8353
Willy Tarreau87cf5142011-08-19 22:57:24 +02008354 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008355 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8356 "forwardfor", proxy_type_str(curproxy), curproxy->id);
8357 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02008358 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008359 }
8360
8361 if (curproxy->options & PR_O_ORGTO) {
8362 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8363 "originalto", proxy_type_str(curproxy), curproxy->id);
8364 err_code |= ERR_WARN;
8365 curproxy->options &= ~PR_O_ORGTO;
8366 }
8367
8368 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
8369 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
8370 (curproxy->cap & cfg_opts[optnum].cap) &&
8371 (curproxy->options & cfg_opts[optnum].val)) {
8372 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8373 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
8374 err_code |= ERR_WARN;
8375 curproxy->options &= ~cfg_opts[optnum].val;
8376 }
8377 }
8378
8379 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
8380 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
8381 (curproxy->cap & cfg_opts2[optnum].cap) &&
8382 (curproxy->options2 & cfg_opts2[optnum].val)) {
8383 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8384 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
8385 err_code |= ERR_WARN;
8386 curproxy->options2 &= ~cfg_opts2[optnum].val;
8387 }
8388 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008389
Willy Tarreau29fbe512015-08-20 19:35:14 +02008390#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008391 if (curproxy->conn_src.bind_hdr_occ) {
8392 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008393 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01008394 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008395 err_code |= ERR_WARN;
8396 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008397#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008398 }
8399
Willy Tarreaubaaee002006-06-26 02:48:02 +02008400 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01008401 * ensure that we're not cross-dressing a TCP server into HTTP.
8402 */
8403 newsrv = curproxy->srv;
8404 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01008405 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008406 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
8407 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008408 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01008409 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008410
Willy Tarreau0cec3312011-10-31 13:49:26 +01008411 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
8412 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
8413 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8414 err_code |= ERR_WARN;
8415 }
8416
Willy Tarreauc93cd162014-05-13 15:54:22 +02008417 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02008418 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
8419 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8420 err_code |= ERR_WARN;
8421 }
8422
Willy Tarreau29fbe512015-08-20 19:35:14 +02008423#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008424 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
8425 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008426 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 +01008427 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008428 err_code |= ERR_WARN;
8429 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008430#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01008431 newsrv = newsrv->next;
8432 }
8433
Willy Tarreaue42bd962014-09-16 16:21:19 +02008434 /* check if we have a frontend with "tcp-request content" looking at L7
8435 * with no inspect-delay
8436 */
8437 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
8438 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008439 if (trule->action == ACT_TCP_CAPTURE &&
Thierry FOURNIERd0d65ae2015-08-04 08:21:12 +02008440 !(trule->arg.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008441 break;
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008442 if ((trule->action >= ACT_ACTION_TRK_SC0 && trule->action <= ACT_ACTION_TRK_SCMAX) &&
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008443 !(trule->arg.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008444 break;
8445 }
8446
8447 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
8448 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
8449 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
8450 " This means that these rules will randomly find their contents. This can be fixed by"
8451 " setting the tcp-request inspect-delay.\n",
8452 proxy_type_str(curproxy), curproxy->id);
8453 err_code |= ERR_WARN;
8454 }
8455 }
8456
Willy Tarreauc1a21672009-08-16 22:37:44 +02008457 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02008458 if (!curproxy->accept)
8459 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02008460
Willy Tarreauc1a21672009-08-16 22:37:44 +02008461 if (curproxy->tcp_req.inspect_delay ||
8462 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02008463 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008464
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008465 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008466 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008467 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008468 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008469
8470 /* both TCP and HTTP must check switching rules */
8471 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
8472 }
8473
8474 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02008475 if (curproxy->tcp_req.inspect_delay ||
8476 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
8477 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
8478
Emeric Brun97679e72010-09-23 17:56:44 +02008479 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
8480 curproxy->be_rsp_ana |= AN_RES_INSPECT;
8481
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008482 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008483 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008484 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008485 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008486
8487 /* If the backend does requires RDP cookie persistence, we have to
8488 * enable the corresponding analyser.
8489 */
8490 if (curproxy->options2 & PR_O2_RDPC_PRST)
8491 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
8492 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008493 }
8494
8495 /***********************************************************/
8496 /* At this point, target names have already been resolved. */
8497 /***********************************************************/
8498
8499 /* Check multi-process mode compatibility */
8500
8501 if (global.nbproc > 1 && global.stats_fe) {
8502 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8503 unsigned long mask;
8504
8505 mask = nbits(global.nbproc);
8506 if (global.stats_fe->bind_proc)
8507 mask &= global.stats_fe->bind_proc;
8508
8509 if (bind_conf->bind_proc)
8510 mask &= bind_conf->bind_proc;
8511
8512 /* stop here if more than one process is used */
David Carliere6c39412015-07-02 07:00:17 +00008513 if (my_popcountl(mask) > 1)
Willy Tarreau419ead82014-09-16 13:41:21 +02008514 break;
8515 }
8516 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
8517 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");
8518 }
8519 }
8520
8521 /* Make each frontend inherit bind-process from its listeners when not specified. */
8522 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8523 if (curproxy->bind_proc)
8524 continue;
8525
8526 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8527 unsigned long mask;
8528
Willy Tarreaue428b082015-05-04 21:57:58 +02008529 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008530 curproxy->bind_proc |= mask;
8531 }
8532
8533 if (!curproxy->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008534 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008535 }
8536
8537 if (global.stats_fe) {
8538 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8539 unsigned long mask;
8540
Willy Tarreaue428b082015-05-04 21:57:58 +02008541 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008542 global.stats_fe->bind_proc |= mask;
8543 }
8544 if (!global.stats_fe->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008545 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008546 }
8547
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02008548 /* propagate bindings from frontends to backends. Don't do it if there
8549 * are any fatal errors as we must not call it with unresolved proxies.
8550 */
8551 if (!cfgerr) {
8552 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8553 if (curproxy->cap & PR_CAP_FE)
8554 propagate_processes(curproxy, NULL);
8555 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008556 }
8557
8558 /* Bind each unbound backend to all processes when not specified. */
8559 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8560 if (curproxy->bind_proc)
8561 continue;
Willy Tarreaue428b082015-05-04 21:57:58 +02008562 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008563 }
8564
8565 /*******************************************************/
8566 /* At this step, all proxies have a non-null bind_proc */
8567 /*******************************************************/
8568
8569 /* perform the final checks before creating tasks */
8570
8571 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8572 struct listener *listener;
8573 unsigned int next_id;
8574 int nbproc;
8575
David Carliere6c39412015-07-02 07:00:17 +00008576 nbproc = my_popcountl(curproxy->bind_proc & nbits(global.nbproc));
Willy Tarreauc1a21672009-08-16 22:37:44 +02008577
Emeric Brunc52962f2012-11-15 18:28:02 +01008578#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008579 /* Configure SSL for each bind line.
8580 * Note: if configuration fails at some point, the ->ctx member
8581 * remains NULL so that listeners can later detach.
8582 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008583 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008584 int alloc_ctx;
8585
Emeric Brunc52962f2012-11-15 18:28:02 +01008586 if (!bind_conf->is_ssl) {
8587 if (bind_conf->default_ctx) {
8588 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
8589 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
8590 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008591 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01008592 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008593 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02008594 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008595 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008596 cfgerr++;
8597 continue;
8598 }
8599
Emeric Brun8dc60392014-05-09 13:52:00 +02008600 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008601 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02008602 if (alloc_ctx == SHCTX_E_INIT_LOCK)
8603 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");
8604 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008605 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02008606 cfgerr++;
8607 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008608 }
8609
Emeric Brunfc0421f2012-09-07 17:30:07 +02008610 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008611 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008612
8613 /* initialize CA variables if the certificates generation is enabled */
8614 cfgerr += ssl_sock_load_ca(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008615 }
Emeric Brunc52962f2012-11-15 18:28:02 +01008616#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008617
Willy Tarreaue6b98942007-10-29 01:09:36 +01008618 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008619 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008620 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008621 if (!listener->luid) {
8622 /* listener ID not set, use automatic numbering with first
8623 * spare entry starting with next_luid.
8624 */
8625 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
8626 listener->conf.id.key = listener->luid = next_id;
8627 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008628 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01008629 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008630
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008631 /* enable separate counters */
8632 if (curproxy->options2 & PR_O2_SOCKSTAT) {
8633 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01008634 if (!listener->name)
8635 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008636 }
Willy Tarreau81796be2012-09-22 19:11:47 +02008637
Willy Tarreaue6b98942007-10-29 01:09:36 +01008638 if (curproxy->options & PR_O_TCP_NOLING)
8639 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02008640 if (!listener->maxconn)
8641 listener->maxconn = curproxy->maxconn;
8642 if (!listener->backlog)
8643 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01008644 if (!listener->maxaccept)
8645 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
8646
8647 /* we want to have an optimal behaviour on single process mode to
8648 * maximize the work at once, but in multi-process we want to keep
8649 * some fairness between processes, so we target half of the max
8650 * number of events to be balanced over all the processes the proxy
8651 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
8652 * used to disable the limit.
8653 */
8654 if (listener->maxaccept > 0) {
8655 if (nbproc > 1)
8656 listener->maxaccept = (listener->maxaccept + 1) / 2;
8657 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
8658 }
8659
Willy Tarreau9903f0e2015-04-04 18:50:31 +02008660 listener->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02008661 listener->handler = process_stream;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008662 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01008663 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01008664
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008665 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
8666 listener->options |= LI_O_TCP_RULES;
8667
Willy Tarreaude3041d2010-05-31 10:56:17 +02008668 if (curproxy->mon_mask.s_addr)
8669 listener->options |= LI_O_CHK_MONNET;
8670
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008671 /* smart accept mode is automatic in HTTP mode */
8672 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008673 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008674 !(curproxy->no_options2 & PR_O2_SMARTACC)))
8675 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01008676 }
8677
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008678 /* Release unused SSL configs */
8679 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8680 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008681 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008682#ifdef USE_OPENSSL
Christopher Faulet31af49d2015-06-09 17:29:50 +02008683 ssl_sock_free_ca(bind_conf);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008684 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008685 free(bind_conf->ca_file);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008686 free(bind_conf->ca_sign_file);
8687 free(bind_conf->ca_sign_pass);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008688 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02008689 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008690 free(bind_conf->crl_file);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008691 if(bind_conf->keys_ref) {
8692 free(bind_conf->keys_ref->filename);
8693 free(bind_conf->keys_ref->tlskeys);
8694 free(bind_conf->keys_ref);
8695 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008696#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008697 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008698
Willy Tarreau102df612014-05-07 23:56:38 +02008699 if (nbproc > 1) {
8700 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02008701 int count, maxproc = 0;
8702
8703 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
David Carliere6c39412015-07-02 07:00:17 +00008704 count = my_popcountl(bind_conf->bind_proc);
Willy Tarreaueb791e02014-09-16 15:11:04 +02008705 if (count > maxproc)
8706 maxproc = count;
8707 }
8708 /* backends have 0, frontends have 1 or more */
8709 if (maxproc != 1)
8710 Warning("Proxy '%s': in multi-process mode, stats will be"
8711 " limited to process assigned to the current request.\n",
8712 curproxy->id);
8713
Willy Tarreau102df612014-05-07 23:56:38 +02008714 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
8715 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
8716 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008717 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008718 }
Willy Tarreau102df612014-05-07 23:56:38 +02008719 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
8720 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
8721 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008722 }
8723 }
Willy Tarreau918ff602011-07-25 16:33:49 +02008724
8725 /* create the task associated with the proxy */
8726 curproxy->task = task_new();
8727 if (curproxy->task) {
8728 curproxy->task->context = curproxy;
8729 curproxy->task->process = manage_proxy;
8730 /* no need to queue, it will be done automatically if some
8731 * listener gets limited.
8732 */
8733 curproxy->task->expire = TICK_ETERNITY;
8734 } else {
8735 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
8736 curproxy->id);
8737 cfgerr++;
8738 }
Willy Tarreaub369a042014-09-16 13:21:03 +02008739 }
8740
Willy Tarreaufbb78422011-06-05 15:38:35 +02008741 /* automatically compute fullconn if not set. We must not do it in the
8742 * loop above because cross-references are not yet fully resolved.
8743 */
8744 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8745 /* If <fullconn> is not set, let's set it to 10% of the sum of
8746 * the possible incoming frontend's maxconns.
8747 */
8748 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
8749 struct proxy *fe;
8750 int total = 0;
8751
8752 /* sum up the number of maxconns of frontends which
8753 * reference this backend at least once or which are
8754 * the same one ('listen').
8755 */
8756 for (fe = proxy; fe; fe = fe->next) {
8757 struct switching_rule *rule;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008758 int found = 0;
8759
8760 if (!(fe->cap & PR_CAP_FE))
8761 continue;
8762
8763 if (fe == curproxy) /* we're on a "listen" instance */
8764 found = 1;
8765
8766 if (fe->defbe.be == curproxy) /* "default_backend" */
8767 found = 1;
8768
8769 /* check if a "use_backend" rule matches */
8770 if (!found) {
8771 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01008772 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02008773 found = 1;
8774 break;
8775 }
8776 }
8777 }
8778
Willy Tarreaufbb78422011-06-05 15:38:35 +02008779 /* now we've checked all possible ways to reference a backend
8780 * from a frontend.
8781 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02008782 if (!found)
8783 continue;
8784 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008785 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02008786 /* we have the sum of the maxconns in <total>. We only
8787 * keep 10% of that sum to set the default fullconn, with
8788 * a hard minimum of 1 (to avoid a divide by zero).
8789 */
8790 curproxy->fullconn = (total + 9) / 10;
8791 if (!curproxy->fullconn)
8792 curproxy->fullconn = 1;
8793 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01008794 }
8795
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008796 /*
8797 * Recount currently required checks.
8798 */
8799
8800 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
8801 int optnum;
8802
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008803 for (optnum = 0; cfg_opts[optnum].name; optnum++)
8804 if (curproxy->options & cfg_opts[optnum].val)
8805 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008806
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008807 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
8808 if (curproxy->options2 & cfg_opts2[optnum].val)
8809 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008810 }
8811
Willy Tarreau0fca4832015-05-01 19:12:05 +02008812 /* compute the required process bindings for the peers */
8813 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
8814 if (curproxy->table.peers.p)
8815 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
8816
Willy Tarreau122541c2011-09-07 21:24:49 +02008817 if (peers) {
8818 struct peers *curpeers = peers, **last;
8819 struct peer *p, *pb;
8820
Willy Tarreau1e273012015-05-01 19:15:17 +02008821 /* Remove all peers sections which don't have a valid listener,
8822 * which are not used by any table, or which are bound to more
8823 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02008824 */
8825 last = &peers;
8826 while (*last) {
8827 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008828
8829 if (curpeers->state == PR_STSTOPPED) {
8830 /* the "disabled" keyword was present */
8831 if (curpeers->peers_fe)
8832 stop_proxy(curpeers->peers_fe);
8833 curpeers->peers_fe = NULL;
8834 }
8835 else if (!curpeers->peers_fe) {
8836 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
8837 curpeers->id, localpeer);
8838 }
David Carliere6c39412015-07-02 07:00:17 +00008839 else if (my_popcountl(curpeers->peers_fe->bind_proc) != 1) {
Willy Tarreau1e273012015-05-01 19:15:17 +02008840 /* either it's totally stopped or too much used */
8841 if (curpeers->peers_fe->bind_proc) {
8842 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreau64c57222015-05-04 21:48:51 +02008843 "running in different processes (%d different ones). "
8844 "Check global.nbproc and all tables' bind-process "
David Carliere6c39412015-07-02 07:00:17 +00008845 "settings.\n", curpeers->id, my_popcountl(curpeers->peers_fe->bind_proc));
Willy Tarreau1e273012015-05-01 19:15:17 +02008846 cfgerr++;
8847 }
8848 stop_proxy(curpeers->peers_fe);
8849 curpeers->peers_fe = NULL;
8850 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008851 else {
Emeric Brunb3971ab2015-05-12 18:49:09 +02008852 peers_init_sync(curpeers);
Willy Tarreau122541c2011-09-07 21:24:49 +02008853 last = &curpeers->next;
8854 continue;
8855 }
8856
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008857 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02008858 p = curpeers->remote;
8859 while (p) {
8860 pb = p->next;
8861 free(p->id);
8862 free(p);
8863 p = pb;
8864 }
8865
8866 /* Destroy and unlink this curpeers section.
8867 * Note: curpeers is backed up into *last.
8868 */
8869 free(curpeers->id);
8870 curpeers = curpeers->next;
8871 free(*last);
8872 *last = curpeers;
8873 }
8874 }
8875
Willy Tarreau6866f3f2015-05-01 19:09:08 +02008876 /* initialize stick-tables on backend capable proxies. This must not
8877 * be done earlier because the data size may be discovered while parsing
8878 * other proxies.
8879 */
8880 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8881 if (curproxy->state == PR_STSTOPPED)
8882 continue;
8883
8884 if (!stktable_init(&curproxy->table)) {
8885 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
8886 cfgerr++;
8887 }
8888 }
8889
Simon Horman0d16a402015-01-30 11:22:58 +09008890 if (mailers) {
8891 struct mailers *curmailers = mailers, **last;
8892 struct mailer *m, *mb;
8893
8894 /* Remove all mailers sections which don't have a valid listener.
8895 * This can happen when a mailers section is never referenced.
8896 */
8897 last = &mailers;
8898 while (*last) {
8899 curmailers = *last;
8900 if (curmailers->users) {
8901 last = &curmailers->next;
8902 continue;
8903 }
8904
8905 Warning("Removing incomplete section 'mailers %s'.\n",
8906 curmailers->id);
8907
8908 m = curmailers->mailer_list;
8909 while (m) {
8910 mb = m->next;
8911 free(m->id);
8912 free(m);
8913 m = mb;
8914 }
8915
8916 /* Destroy and unlink this curmailers section.
8917 * Note: curmailers is backed up into *last.
8918 */
8919 free(curmailers->id);
8920 curmailers = curmailers->next;
8921 free(*last);
8922 *last = curmailers;
8923 }
8924 }
8925
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02008926 /* Update server_state_file_name to backend name if backend is supposed to use
8927 * a server-state file locally defined and none has been provided */
8928 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8929 if (curproxy->load_server_state_from_file == PR_SRV_STATE_FILE_LOCAL &&
8930 curproxy->server_state_file_name == NULL)
8931 curproxy->server_state_file_name = strdup(curproxy->id);
8932 }
8933
Willy Tarreau34eb6712011-10-24 18:15:04 +02008934 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02008935 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02008936 MEM_F_SHARED);
8937
Willy Tarreaubb925012009-07-23 13:36:36 +02008938 if (cfgerr > 0)
8939 err_code |= ERR_ALERT | ERR_FATAL;
8940 out:
8941 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02008942}
8943
Willy Tarreau5b2c3362008-07-09 19:39:06 +02008944/*
8945 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
8946 * parsing sessions.
8947 */
8948void cfg_register_keywords(struct cfg_kw_list *kwl)
8949{
8950 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
8951}
Willy Tarreaubaaee002006-06-26 02:48:02 +02008952
Willy Tarreau5b2c3362008-07-09 19:39:06 +02008953/*
8954 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
8955 */
8956void cfg_unregister_keywords(struct cfg_kw_list *kwl)
8957{
8958 LIST_DEL(&kwl->list);
8959 LIST_INIT(&kwl->list);
8960}
Willy Tarreaubaaee002006-06-26 02:48:02 +02008961
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01008962/* this function register new section in the haproxy configuration file.
8963 * <section_name> is the name of this new section and <section_parser>
8964 * is the called parser. If two section declaration have the same name,
8965 * only the first declared is used.
8966 */
8967int cfg_register_section(char *section_name,
8968 int (*section_parser)(const char *, int, char **, int))
8969{
8970 struct cfg_section *cs;
8971
8972 cs = calloc(1, sizeof(*cs));
8973 if (!cs) {
8974 Alert("register section '%s': out of memory.\n", section_name);
8975 return 0;
8976 }
8977
8978 cs->section_name = section_name;
8979 cs->section_parser = section_parser;
8980
8981 LIST_ADDQ(&sections, &cs->list);
8982
8983 return 1;
8984}
8985
Willy Tarreaubaaee002006-06-26 02:48:02 +02008986/*
David Carlier845efb52015-09-25 11:49:18 +01008987 * free all config section entries
8988 */
8989void cfg_unregister_sections(void)
8990{
8991 struct cfg_section *cs, *ics;
8992
8993 list_for_each_entry_safe(cs, ics, &sections, list) {
8994 LIST_DEL(&cs->list);
8995 free(cs);
8996 }
8997}
8998
8999/*
Willy Tarreaubaaee002006-06-26 02:48:02 +02009000 * Local variables:
9001 * c-indent-level: 8
9002 * c-basic-offset: 8
9003 * End:
9004 */