blob: 39ee3598808b63d231ecd02baeb95f14c01188c8 [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);
Willy Tarreau18324f52014-06-27 18:10:07 +02001575 logline = realloc(logline, global.max_syslog_len + 1);
1576 }
1577
William Lallemand1a748ae2015-05-19 16:37:23 +02001578 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
1579 goto out;
1580
Willy Tarreau18324f52014-06-27 18:10:07 +02001581 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001582 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001583 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001584 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001585 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001586 }
1587
William Lallemand0f99e342011-10-12 17:50:54 +02001588 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02001589 if (*(args[arg+3])) {
1590 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001591 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001592 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001593 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001594 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001595 }
1596 }
1597
William Lallemand0f99e342011-10-12 17:50:54 +02001598 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02001599 if (*(args[arg+4])) {
1600 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001601 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001602 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001603 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001604 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001605 }
1606 }
1607
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02001608 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001609 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001610 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001611 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001612 free(logsrv);
1613 goto out;
1614 }
1615 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001616
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001617 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001618 if (port1 != port2) {
1619 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1620 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001621 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001622 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001623 goto out;
1624 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001625
William Lallemand0f99e342011-10-12 17:50:54 +02001626 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001627 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001628 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001629 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001630
William Lallemand0f99e342011-10-12 17:50:54 +02001631 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001632 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001633 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1634 char *name;
1635 int len;
1636
1637 if (global.log_send_hostname != NULL) {
1638 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1639 err_code |= ERR_ALERT;
1640 goto out;
1641 }
1642
1643 if (*(args[1]))
1644 name = args[1];
1645 else
1646 name = hostname;
1647
1648 len = strlen(name);
1649
1650 /* We'll add a space after the name to respect the log format */
1651 free(global.log_send_hostname);
1652 global.log_send_hostname = malloc(len + 2);
1653 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1654 }
Baptiste Assmann6bc89362015-08-23 09:22:25 +02001655 else if (!strcmp(args[0], "server-state-base")) { /* path base where HAProxy can find server state files */
1656 if (global.server_state_base != NULL) {
1657 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1658 err_code |= ERR_ALERT;
1659 goto out;
1660 }
1661
1662 if (!*(args[1])) {
1663 Alert("parsing [%s:%d] : '%s' expects one argument: a directory path.\n", file, linenum, args[0]);
1664 err_code |= ERR_FATAL;
1665 goto out;
1666 }
1667
1668 global.server_state_base = strdup(args[1]);
1669 }
Baptiste Assmanne0882262015-08-23 09:54:31 +02001670 else if (!strcmp(args[0], "server-state-file")) { /* path to the file where HAProxy can load the server states */
1671 if (global.server_state_file != NULL) {
1672 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1673 err_code |= ERR_ALERT;
1674 goto out;
1675 }
1676
1677 if (!*(args[1])) {
1678 Alert("parsing [%s:%d] : '%s' expect one argument: a file path.\n", file, linenum, args[0]);
1679 err_code |= ERR_FATAL;
1680 goto out;
1681 }
1682
1683 global.server_state_file = strdup(args[1]);
1684 }
Kevinm48936af2010-12-22 16:08:21 +00001685 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
William Lallemand1a748ae2015-05-19 16:37:23 +02001686 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1687 goto out;
Kevinm48936af2010-12-22 16:08:21 +00001688 if (*(args[1]) == 0) {
1689 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1690 err_code |= ERR_ALERT | ERR_FATAL;
1691 goto out;
1692 }
1693 free(global.log_tag);
1694 global.log_tag = strdup(args[1]);
1695 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001696 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
William Lallemand1a748ae2015-05-19 16:37:23 +02001697 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1698 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001699 if (global.spread_checks != 0) {
1700 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001701 err_code |= ERR_ALERT;
1702 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001703 }
1704 if (*(args[1]) == 0) {
1705 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001706 err_code |= ERR_ALERT | ERR_FATAL;
1707 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001708 }
1709 global.spread_checks = atol(args[1]);
1710 if (global.spread_checks < 0 || global.spread_checks > 50) {
1711 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001712 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001713 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001714 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001715 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1716 const char *err;
1717 unsigned int val;
1718
William Lallemand1a748ae2015-05-19 16:37:23 +02001719 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1720 goto out;
Willy Tarreau1746eec2014-04-25 10:46:47 +02001721 if (*(args[1]) == 0) {
1722 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1723 err_code |= ERR_ALERT | ERR_FATAL;
1724 goto out;
1725 }
1726
1727 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1728 if (err) {
1729 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1730 err_code |= ERR_ALERT | ERR_FATAL;
1731 }
1732 global.max_spread_checks = val;
1733 if (global.max_spread_checks < 0) {
1734 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1735 err_code |= ERR_ALERT | ERR_FATAL;
1736 }
1737 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001738 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1739#ifdef USE_CPU_AFFINITY
1740 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001741 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001742 unsigned long cpus = 0;
1743
1744 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001745 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001746 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001747 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001748 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001749 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001750 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001751 proc = atol(args[1]);
1752 if (proc >= 1 && proc <= LONGBITS)
1753 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001754 }
1755
1756 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001757 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",
1758 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001759 err_code |= ERR_ALERT | ERR_FATAL;
1760 goto out;
1761 }
1762
1763 cur_arg = 2;
1764 while (*args[cur_arg]) {
1765 unsigned int low, high;
1766
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001767 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001768 char *dash = strchr(args[cur_arg], '-');
1769
1770 low = high = str2uic(args[cur_arg]);
1771 if (dash)
1772 high = str2uic(dash + 1);
1773
1774 if (high < low) {
1775 unsigned int swap = low;
1776 low = high;
1777 high = swap;
1778 }
1779
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001780 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001781 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001782 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001783 err_code |= ERR_ALERT | ERR_FATAL;
1784 goto out;
1785 }
1786
1787 while (low <= high)
1788 cpus |= 1UL << low++;
1789 }
1790 else {
1791 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1792 file, linenum, args[0], args[cur_arg]);
1793 err_code |= ERR_ALERT | ERR_FATAL;
1794 goto out;
1795 }
1796 cur_arg++;
1797 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001798 for (i = 0; i < LONGBITS; i++)
1799 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001800 global.cpu_map[i] = cpus;
1801#else
1802 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1803 err_code |= ERR_ALERT | ERR_FATAL;
1804 goto out;
1805#endif
1806 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001807 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001808 struct cfg_kw_list *kwl;
1809 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001810 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001811
1812 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1813 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1814 if (kwl->kw[index].section != CFG_GLOBAL)
1815 continue;
1816 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001817 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001818 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001819 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001820 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001821 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001822 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001823 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001824 err_code |= ERR_WARN;
1825 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001826 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001827 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001828 }
1829 }
1830 }
1831
Willy Tarreaubaaee002006-06-26 02:48:02 +02001832 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001833 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001834 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001835
Willy Tarreau058e9072009-07-20 09:30:05 +02001836 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001837 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001838 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001839}
1840
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001841void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001842{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001843 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001844 defproxy.mode = PR_MODE_TCP;
1845 defproxy.state = PR_STNEW;
1846 defproxy.maxconn = cfg_maxpconn;
1847 defproxy.conn_retries = CONN_RETRIES;
Joseph Lynch726ab712015-05-11 23:25:34 -07001848 defproxy.redispatch_after = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001849
Simon Horman66183002013-02-23 10:16:43 +09001850 defproxy.defsrv.check.inter = DEF_CHKINTR;
1851 defproxy.defsrv.check.fastinter = 0;
1852 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001853 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1854 defproxy.defsrv.agent.fastinter = 0;
1855 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001856 defproxy.defsrv.check.rise = DEF_RISETIME;
1857 defproxy.defsrv.check.fall = DEF_FALLTIME;
1858 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1859 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001860 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001861 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001862 defproxy.defsrv.maxqueue = 0;
1863 defproxy.defsrv.minconn = 0;
1864 defproxy.defsrv.maxconn = 0;
1865 defproxy.defsrv.slowstart = 0;
1866 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1867 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1868 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Simon Horman64e34162015-02-06 11:11:57 +09001869
1870 defproxy.email_alert.level = LOG_ALERT;
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02001871 defproxy.load_server_state_from_file = PR_SRV_STATE_FILE_UNSPEC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001872}
1873
Willy Tarreauade5ec42010-01-28 19:33:49 +01001874
Willy Tarreau63af98d2014-05-18 08:11:41 +02001875/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1876 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1877 * ERR_FATAL in case of error.
1878 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001879static int create_cond_regex_rule(const char *file, int line,
1880 struct proxy *px, int dir, int action, int flags,
1881 const char *cmd, const char *reg, const char *repl,
1882 const char **cond_start)
1883{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001884 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001885 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001886 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001887 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001888 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001889 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001890 int cs;
1891 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001892
1893 if (px == &defproxy) {
1894 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001895 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001896 goto err;
1897 }
1898
1899 if (*reg == 0) {
1900 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001901 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001902 goto err;
1903 }
1904
1905 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001906 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001907
Willy Tarreau5321c422010-01-28 20:35:13 +01001908 if (cond_start &&
1909 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001910 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1911 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1912 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001913 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001914 goto err;
1915 }
1916 }
1917 else if (cond_start && **cond_start) {
1918 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1919 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001920 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001921 goto err;
1922 }
1923
Willy Tarreau63af98d2014-05-18 08:11:41 +02001924 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001925 (dir == SMP_OPT_DIR_REQ) ?
1926 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1927 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1928 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001929
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001930 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001931 if (!preg) {
1932 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001933 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001934 goto err;
1935 }
1936
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001937 cs = !(flags & REG_ICASE);
1938 cap = !(flags & REG_NOSUB);
1939 error = NULL;
1940 if (!regex_comp(reg, preg, cs, cap, &error)) {
1941 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1942 free(error);
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
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001947 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001948 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001949 if (repl && err) {
1950 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1951 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001952 ret_code |= ERR_ALERT | ERR_FATAL;
1953 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001954 }
1955
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001956 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001957 ret_code |= ERR_WARN;
1958
1959 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001960
Willy Tarreau63af98d2014-05-18 08:11:41 +02001961 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001962 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001963 err:
1964 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001965 free(errmsg);
1966 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001967}
1968
Willy Tarreaubaaee002006-06-26 02:48:02 +02001969/*
William Lallemand51097192015-04-14 16:35:22 +02001970 * Parse a line in a <listen>, <frontend> or <backend> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001971 * Returns the error code, 0 if OK, or any combination of :
1972 * - ERR_ABORT: must abort ASAP
1973 * - ERR_FATAL: we can continue parsing but not start the service
1974 * - ERR_WARN: a warning has been emitted
1975 * - ERR_ALERT: an alert has been emitted
1976 * Only the two first ones can stop processing, the two others are just
1977 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001978 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001979int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1980{
1981 static struct peers *curpeers = NULL;
1982 struct peer *newpeer = NULL;
1983 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001984 struct bind_conf *bind_conf;
1985 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001986 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001987 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001988
1989 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001990 if (!*args[1]) {
1991 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001992 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001993 goto out;
1994 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001995
William Lallemand6e62fb62015-04-28 16:55:23 +02001996 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1997 goto out;
1998
Emeric Brun32da3c42010-09-23 18:39:19 +02001999 err = invalid_char(args[1]);
2000 if (err) {
2001 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2002 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01002003 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002004 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002005 }
2006
2007 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
2008 /*
2009 * If there are two proxies with the same name only following
2010 * combinations are allowed:
2011 */
2012 if (strcmp(curpeers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002013 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 +02002014 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002015 err_code |= ERR_ALERT | ERR_FATAL;
Emeric Brun32da3c42010-09-23 18:39:19 +02002016 }
2017 }
2018
2019 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
2020 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2021 err_code |= ERR_ALERT | ERR_ABORT;
2022 goto out;
2023 }
2024
2025 curpeers->next = peers;
2026 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002027 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002028 curpeers->conf.line = linenum;
2029 curpeers->last_change = now.tv_sec;
2030 curpeers->id = strdup(args[1]);
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002031 curpeers->state = PR_STNEW;
Emeric Brun32da3c42010-09-23 18:39:19 +02002032 }
2033 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01002034 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01002035 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002036 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02002037
2038 if (!*args[2]) {
2039 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2040 file, linenum, args[0]);
2041 err_code |= ERR_ALERT | ERR_FATAL;
2042 goto out;
2043 }
2044
2045 err = invalid_char(args[1]);
2046 if (err) {
2047 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2048 file, linenum, *err, args[1]);
2049 err_code |= ERR_ALERT | ERR_FATAL;
2050 goto out;
2051 }
2052
2053 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
2054 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2055 err_code |= ERR_ALERT | ERR_ABORT;
2056 goto out;
2057 }
2058
2059 /* the peers are linked backwards first */
2060 curpeers->count++;
2061 newpeer->next = curpeers->remote;
2062 curpeers->remote = newpeer;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002063 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002064 newpeer->conf.line = linenum;
2065
2066 newpeer->last_change = now.tv_sec;
2067 newpeer->id = strdup(args[1]);
2068
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002069 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002070 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01002071 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002072 err_code |= ERR_ALERT | ERR_FATAL;
2073 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002074 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01002075
2076 proto = protocol_by_family(sk->ss_family);
2077 if (!proto || !proto->connect) {
2078 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2079 file, linenum, args[0], args[1]);
2080 err_code |= ERR_ALERT | ERR_FATAL;
2081 goto out;
2082 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002083
2084 if (port1 != port2) {
2085 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2086 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002087 err_code |= ERR_ALERT | ERR_FATAL;
2088 goto out;
2089 }
2090
Willy Tarreau2aa38802013-02-20 19:20:59 +01002091 if (!port1) {
2092 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2093 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002094 err_code |= ERR_ALERT | ERR_FATAL;
2095 goto out;
2096 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002097
Emeric Brun32da3c42010-09-23 18:39:19 +02002098 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002099 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002100 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02002101 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02002102
Emeric Brun32da3c42010-09-23 18:39:19 +02002103 if (strcmp(newpeer->id, localpeer) == 0) {
2104 /* Current is local peer, it define a frontend */
2105 newpeer->local = 1;
Emeric Brunb3971ab2015-05-12 18:49:09 +02002106 peers->local = newpeer;
Emeric Brun32da3c42010-09-23 18:39:19 +02002107
2108 if (!curpeers->peers_fe) {
2109 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
2110 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2111 err_code |= ERR_ALERT | ERR_ABORT;
2112 goto out;
2113 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002114
Willy Tarreau237250c2011-07-29 01:49:03 +02002115 init_new_proxy(curpeers->peers_fe);
2116 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02002117 curpeers->peers_fe->id = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002118 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
2119 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau91d96282015-03-13 15:47:26 +01002120 peers_setup_frontend(curpeers->peers_fe);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002121
2122 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
2123
Willy Tarreau902636f2013-03-10 19:44:48 +01002124 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
2125 if (errmsg && *errmsg) {
2126 indent_msg(&errmsg, 2);
2127 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002128 }
2129 else
2130 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
2131 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002132 err_code |= ERR_FATAL;
2133 goto out;
2134 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02002135
2136 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01002137 l->maxaccept = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002138 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
2139 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
Willy Tarreau9903f0e2015-04-04 18:50:31 +02002140 l->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02002141 l->handler = process_stream;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002142 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01002143 l->default_target = ((struct proxy *)curpeers->peers_fe)->default_target;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002144 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
2145 global.maxsock += l->maxconn;
2146 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002147 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01002148 else {
2149 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
2150 file, linenum, args[0], args[1],
2151 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
2152 err_code |= ERR_FATAL;
2153 goto out;
2154 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002155 }
2156 } /* neither "peer" nor "peers" */
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002157 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
2158 curpeers->state = PR_STSTOPPED;
2159 }
2160 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
2161 curpeers->state = PR_STNEW;
2162 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002163 else if (*args[0] != 0) {
2164 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2165 err_code |= ERR_ALERT | ERR_FATAL;
2166 goto out;
2167 }
2168
2169out:
Willy Tarreau902636f2013-03-10 19:44:48 +01002170 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02002171 return err_code;
2172}
2173
Baptiste Assmann325137d2015-04-13 23:40:55 +02002174/*
2175 * Parse a <resolvers> section.
2176 * Returns the error code, 0 if OK, or any combination of :
2177 * - ERR_ABORT: must abort ASAP
2178 * - ERR_FATAL: we can continue parsing but not start the service
2179 * - ERR_WARN: a warning has been emitted
2180 * - ERR_ALERT: an alert has been emitted
2181 * Only the two first ones can stop processing, the two others are just
2182 * indicators.
2183 */
2184int cfg_parse_resolvers(const char *file, int linenum, char **args, int kwm)
2185{
2186 static struct dns_resolvers *curr_resolvers = NULL;
2187 struct dns_nameserver *newnameserver = NULL;
2188 const char *err;
2189 int err_code = 0;
2190 char *errmsg = NULL;
2191
2192 if (strcmp(args[0], "resolvers") == 0) { /* new resolvers section */
2193 if (!*args[1]) {
2194 Alert("parsing [%s:%d] : missing name for resolvers section.\n", file, linenum);
2195 err_code |= ERR_ALERT | ERR_ABORT;
2196 goto out;
2197 }
2198
2199 err = invalid_char(args[1]);
2200 if (err) {
2201 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2202 file, linenum, *err, args[0], args[1]);
2203 err_code |= ERR_ALERT | ERR_ABORT;
2204 goto out;
2205 }
2206
2207 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
2208 /* Error if two resolvers owns the same name */
2209 if (strcmp(curr_resolvers->id, args[1]) == 0) {
2210 Alert("Parsing [%s:%d]: resolvers '%s' has same name as another resolvers (declared at %s:%d).\n",
2211 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2212 err_code |= ERR_ALERT | ERR_ABORT;
2213 }
2214 }
2215
2216 if ((curr_resolvers = (struct dns_resolvers *)calloc(1, sizeof(struct dns_resolvers))) == NULL) {
2217 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2218 err_code |= ERR_ALERT | ERR_ABORT;
2219 goto out;
2220 }
2221
2222 /* default values */
2223 LIST_ADDQ(&dns_resolvers, &curr_resolvers->list);
2224 curr_resolvers->conf.file = strdup(file);
2225 curr_resolvers->conf.line = linenum;
2226 curr_resolvers->id = strdup(args[1]);
2227 curr_resolvers->query_ids = EB_ROOT;
2228 /* default hold period for valid is 10s */
Baptiste Assmann4c5490a2015-07-14 21:42:49 +02002229 curr_resolvers->hold.valid = 10000;
2230 curr_resolvers->timeout.retry = 1000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002231 curr_resolvers->resolve_retries = 3;
2232 LIST_INIT(&curr_resolvers->nameserver_list);
2233 LIST_INIT(&curr_resolvers->curr_resolution);
2234 }
2235 else if (strcmp(args[0], "nameserver") == 0) { /* nameserver definition */
2236 struct sockaddr_storage *sk;
2237 int port1, port2;
2238 struct protocol *proto;
2239
2240 if (!*args[2]) {
2241 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2242 file, linenum, args[0]);
2243 err_code |= ERR_ALERT | ERR_FATAL;
2244 goto out;
2245 }
2246
2247 err = invalid_char(args[1]);
2248 if (err) {
2249 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2250 file, linenum, *err, args[1]);
2251 err_code |= ERR_ALERT | ERR_FATAL;
2252 goto out;
2253 }
2254
2255 if ((newnameserver = (struct dns_nameserver *)calloc(1, sizeof(struct dns_nameserver))) == NULL) {
2256 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2257 err_code |= ERR_ALERT | ERR_ABORT;
2258 goto out;
2259 }
2260
2261 /* the nameservers are linked backward first */
2262 LIST_ADDQ(&curr_resolvers->nameserver_list, &newnameserver->list);
2263 curr_resolvers->count_nameservers++;
2264 newnameserver->resolvers = curr_resolvers;
2265 newnameserver->conf.file = strdup(file);
2266 newnameserver->conf.line = linenum;
2267 newnameserver->id = strdup(args[1]);
2268
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002269 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002270 if (!sk) {
2271 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2272 err_code |= ERR_ALERT | ERR_FATAL;
2273 goto out;
2274 }
2275
2276 proto = protocol_by_family(sk->ss_family);
2277 if (!proto || !proto->connect) {
2278 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2279 file, linenum, args[0], args[1]);
2280 err_code |= ERR_ALERT | ERR_FATAL;
2281 goto out;
2282 }
2283
2284 if (port1 != port2) {
2285 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2286 file, linenum, args[0], args[1], args[2]);
2287 err_code |= ERR_ALERT | ERR_FATAL;
2288 goto out;
2289 }
2290
2291 newnameserver->addr = *sk;
2292 }
2293 else if (strcmp(args[0], "hold") == 0) { /* hold periods */
2294 const char *res;
2295 unsigned int time;
2296
2297 if (!*args[2]) {
2298 Alert("parsing [%s:%d] : '%s' expects an <event> and a <time> as arguments.\n",
2299 file, linenum, args[0]);
2300 Alert("<event> can be either 'valid', 'nx', 'refused', 'timeout', or 'other'\n");
2301 err_code |= ERR_ALERT | ERR_FATAL;
2302 goto out;
2303 }
2304 res = parse_time_err(args[2], &time, TIME_UNIT_MS);
2305 if (res) {
2306 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2307 file, linenum, *res, args[0]);
2308 err_code |= ERR_ALERT | ERR_FATAL;
2309 goto out;
2310 }
2311 if (strcmp(args[1], "valid") == 0)
2312 curr_resolvers->hold.valid = time;
2313 else {
2314 Alert("parsing [%s:%d] : '%s' unknown <event>: '%s', expects 'valid'\n",
2315 file, linenum, args[0], args[1]);
2316 err_code |= ERR_ALERT | ERR_FATAL;
2317 goto out;
2318 }
2319
2320 }
2321 else if (strcmp(args[0], "resolve_retries") == 0) {
2322 if (!*args[1]) {
2323 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2324 file, linenum, args[0]);
2325 err_code |= ERR_ALERT | ERR_FATAL;
2326 goto out;
2327 }
2328 curr_resolvers->resolve_retries = atoi(args[1]);
2329 }
2330 else if (strcmp(args[0], "timeout") == 0) {
2331 const char *res;
2332 unsigned int timeout_retry;
2333
2334 if (!*args[2]) {
2335 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments.\n",
2336 file, linenum, args[0]);
2337 err_code |= ERR_ALERT | ERR_FATAL;
2338 goto out;
2339 }
2340 res = parse_time_err(args[2], &timeout_retry, TIME_UNIT_MS);
2341 if (res) {
2342 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2343 file, linenum, *res, args[0]);
2344 err_code |= ERR_ALERT | ERR_FATAL;
2345 goto out;
2346 }
2347 curr_resolvers->timeout.retry = timeout_retry;
2348 } /* neither "nameserver" nor "resolvers" */
2349 else if (*args[0] != 0) {
2350 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2351 err_code |= ERR_ALERT | ERR_FATAL;
2352 goto out;
2353 }
2354
2355 out:
2356 free(errmsg);
2357 return err_code;
2358}
Simon Horman0d16a402015-01-30 11:22:58 +09002359
2360/*
William Lallemand51097192015-04-14 16:35:22 +02002361 * Parse a line in a <listen>, <frontend> or <backend> section.
Simon Horman0d16a402015-01-30 11:22:58 +09002362 * Returns the error code, 0 if OK, or any combination of :
2363 * - ERR_ABORT: must abort ASAP
2364 * - ERR_FATAL: we can continue parsing but not start the service
2365 * - ERR_WARN: a warning has been emitted
2366 * - ERR_ALERT: an alert has been emitted
2367 * Only the two first ones can stop processing, the two others are just
2368 * indicators.
2369 */
2370int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
2371{
2372 static struct mailers *curmailers = NULL;
2373 struct mailer *newmailer = NULL;
2374 const char *err;
2375 int err_code = 0;
2376 char *errmsg = NULL;
2377
2378 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
2379 if (!*args[1]) {
2380 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
2381 err_code |= ERR_ALERT | ERR_ABORT;
2382 goto out;
2383 }
2384
2385 err = invalid_char(args[1]);
2386 if (err) {
2387 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2388 file, linenum, *err, args[0], args[1]);
2389 err_code |= ERR_ALERT | ERR_ABORT;
2390 goto out;
2391 }
2392
2393 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
2394 /*
2395 * If there are two proxies with the same name only following
2396 * combinations are allowed:
2397 */
2398 if (strcmp(curmailers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002399 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 +09002400 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002401 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman0d16a402015-01-30 11:22:58 +09002402 }
2403 }
2404
2405 if ((curmailers = (struct mailers *)calloc(1, sizeof(struct mailers))) == NULL) {
2406 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2407 err_code |= ERR_ALERT | ERR_ABORT;
2408 goto out;
2409 }
2410
2411 curmailers->next = mailers;
2412 mailers = curmailers;
2413 curmailers->conf.file = strdup(file);
2414 curmailers->conf.line = linenum;
2415 curmailers->id = strdup(args[1]);
2416 }
2417 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
2418 struct sockaddr_storage *sk;
2419 int port1, port2;
2420 struct protocol *proto;
2421
2422 if (!*args[2]) {
2423 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2424 file, linenum, args[0]);
2425 err_code |= ERR_ALERT | ERR_FATAL;
2426 goto out;
2427 }
2428
2429 err = invalid_char(args[1]);
2430 if (err) {
2431 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2432 file, linenum, *err, args[1]);
2433 err_code |= ERR_ALERT | ERR_FATAL;
2434 goto out;
2435 }
2436
2437 if ((newmailer = (struct mailer *)calloc(1, sizeof(struct mailer))) == NULL) {
2438 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2439 err_code |= ERR_ALERT | ERR_ABORT;
2440 goto out;
2441 }
2442
2443 /* the mailers are linked backwards first */
2444 curmailers->count++;
2445 newmailer->next = curmailers->mailer_list;
2446 curmailers->mailer_list = newmailer;
2447 newmailer->mailers = curmailers;
2448 newmailer->conf.file = strdup(file);
2449 newmailer->conf.line = linenum;
2450
2451 newmailer->id = strdup(args[1]);
2452
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002453 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Simon Horman0d16a402015-01-30 11:22:58 +09002454 if (!sk) {
2455 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2456 err_code |= ERR_ALERT | ERR_FATAL;
2457 goto out;
2458 }
2459
2460 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002461 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2462 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002463 file, linenum, args[0], args[1]);
2464 err_code |= ERR_ALERT | ERR_FATAL;
2465 goto out;
2466 }
2467
2468 if (port1 != port2) {
2469 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2470 file, linenum, args[0], args[1], args[2]);
2471 err_code |= ERR_ALERT | ERR_FATAL;
2472 goto out;
2473 }
2474
2475 if (!port1) {
2476 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2477 file, linenum, args[0], args[1], args[2]);
2478 err_code |= ERR_ALERT | ERR_FATAL;
2479 goto out;
2480 }
2481
2482 newmailer->addr = *sk;
2483 newmailer->proto = proto;
2484 newmailer->xprt = &raw_sock;
2485 newmailer->sock_init_arg = NULL;
2486 } /* neither "mailer" nor "mailers" */
2487 else if (*args[0] != 0) {
2488 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2489 err_code |= ERR_ALERT | ERR_FATAL;
2490 goto out;
2491 }
2492
2493out:
2494 free(errmsg);
2495 return err_code;
2496}
2497
Simon Horman9dc49962015-01-30 11:22:59 +09002498static void free_email_alert(struct proxy *p)
2499{
2500 free(p->email_alert.mailers.name);
2501 p->email_alert.mailers.name = NULL;
2502 free(p->email_alert.from);
2503 p->email_alert.from = NULL;
2504 free(p->email_alert.to);
2505 p->email_alert.to = NULL;
2506 free(p->email_alert.myhostname);
2507 p->email_alert.myhostname = NULL;
2508}
2509
Willy Tarreau3842f002009-06-14 11:39:52 +02002510int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002511{
2512 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002513 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002514 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002515 int rc;
2516 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002517 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002518 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002519 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002520 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002521 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002522
Willy Tarreau977b8e42006-12-29 14:19:17 +01002523 if (!strcmp(args[0], "listen"))
2524 rc = PR_CAP_LISTEN;
2525 else if (!strcmp(args[0], "frontend"))
2526 rc = PR_CAP_FE | PR_CAP_RS;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02002527 else if (!strcmp(args[0], "backend"))
Willy Tarreau977b8e42006-12-29 14:19:17 +01002528 rc = PR_CAP_BE | PR_CAP_RS;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002529 else
2530 rc = PR_CAP_NONE;
2531
2532 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002533 if (!*args[1]) {
2534 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
2535 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
2536 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002537 err_code |= ERR_ALERT | ERR_ABORT;
2538 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002539 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002540
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002541 err = invalid_char(args[1]);
2542 if (err) {
2543 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2544 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002545 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002546 }
2547
Willy Tarreau8f50b682015-05-26 11:45:02 +02002548 curproxy = (rc & PR_CAP_FE) ? proxy_fe_by_name(args[1]) : proxy_be_by_name(args[1]);
2549 if (curproxy) {
2550 Alert("Parsing [%s:%d]: %s '%s' has the same name as %s '%s' declared at %s:%d.\n",
2551 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2552 curproxy->id, curproxy->conf.file, curproxy->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002553 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002554 }
2555
Willy Tarreaubaaee002006-06-26 02:48:02 +02002556 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
2557 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002558 err_code |= ERR_ALERT | ERR_ABORT;
2559 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002560 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002561
Willy Tarreau97cb7802010-01-03 20:23:58 +01002562 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002563 curproxy->next = proxy;
2564 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002565 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2566 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002567 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002568 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002569 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002570 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002571
William Lallemand6e62fb62015-04-28 16:55:23 +02002572 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2573 if (curproxy->cap & PR_CAP_FE)
2574 Alert("parsing [%s:%d] : please use the 'bind' keyword for listening addresses.\n", file, linenum);
2575 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002576 }
2577
2578 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002579 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002580 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002581
Willy Tarreaubaaee002006-06-26 02:48:02 +02002582 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002583 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002584 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002585 curproxy->no_options = defproxy.no_options;
2586 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002587 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002588 curproxy->except_net = defproxy.except_net;
2589 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002590 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002591 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002592
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002593 if (defproxy.fwdfor_hdr_len) {
2594 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2595 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2596 }
2597
Willy Tarreaub86db342009-11-30 11:50:16 +01002598 if (defproxy.orgto_hdr_len) {
2599 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2600 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2601 }
2602
Mark Lamourinec2247f02012-01-04 13:02:01 -05002603 if (defproxy.server_id_hdr_len) {
2604 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2605 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2606 }
2607
Willy Tarreau977b8e42006-12-29 14:19:17 +01002608 if (curproxy->cap & PR_CAP_FE) {
2609 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002610 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002611 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002612
2613 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002614 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2615 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002616
2617 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2618 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002619
Willy Tarreau977b8e42006-12-29 14:19:17 +01002620 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002621 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002622 curproxy->fullconn = defproxy.fullconn;
2623 curproxy->conn_retries = defproxy.conn_retries;
Joseph Lynch726ab712015-05-11 23:25:34 -07002624 curproxy->redispatch_after = defproxy.redispatch_after;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002625 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002626
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002627 if (defproxy.check_req) {
2628 curproxy->check_req = calloc(1, defproxy.check_len);
2629 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2630 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002631 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002632
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002633 if (defproxy.expect_str) {
2634 curproxy->expect_str = strdup(defproxy.expect_str);
2635 if (defproxy.expect_regex) {
2636 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002637 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2638 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002639 }
2640 }
2641
Willy Tarreau67402132012-05-31 20:40:20 +02002642 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002643 if (defproxy.cookie_name)
2644 curproxy->cookie_name = strdup(defproxy.cookie_name);
2645 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002646 if (defproxy.cookie_domain)
2647 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002648
Willy Tarreau31936852010-10-06 16:59:56 +02002649 if (defproxy.cookie_maxidle)
2650 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2651
2652 if (defproxy.cookie_maxlife)
2653 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2654
Emeric Brun647caf12009-06-30 17:57:00 +02002655 if (defproxy.rdp_cookie_name)
2656 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2657 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2658
Willy Tarreau01732802007-11-01 22:48:15 +01002659 if (defproxy.url_param_name)
2660 curproxy->url_param_name = strdup(defproxy.url_param_name);
2661 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002662
Benoitaffb4812009-03-25 13:02:10 +01002663 if (defproxy.hh_name)
2664 curproxy->hh_name = strdup(defproxy.hh_name);
2665 curproxy->hh_len = defproxy.hh_len;
2666 curproxy->hh_match_domain = defproxy.hh_match_domain;
2667
Willy Tarreauef9a3602012-12-08 22:29:20 +01002668 if (defproxy.conn_src.iface_name)
2669 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2670 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002671 curproxy->conn_src.opts = defproxy.conn_src.opts;
Willy Tarreau29fbe512015-08-20 19:35:14 +02002672#if defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002673 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002674#endif
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02002675 curproxy->load_server_state_from_file = defproxy.load_server_state_from_file;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002676 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002677
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002678 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002679 if (defproxy.capture_name)
2680 curproxy->capture_name = strdup(defproxy.capture_name);
2681 curproxy->capture_namelen = defproxy.capture_namelen;
2682 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002683 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002684
Willy Tarreau977b8e42006-12-29 14:19:17 +01002685 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002686 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002687 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002688 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002689 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002690 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002691 curproxy->mon_net = defproxy.mon_net;
2692 curproxy->mon_mask = defproxy.mon_mask;
2693 if (defproxy.monitor_uri)
2694 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2695 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002696 if (defproxy.defbe.name)
2697 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002698
2699 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002700 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2701 if (curproxy->conf.logformat_string &&
2702 curproxy->conf.logformat_string != default_http_log_format &&
2703 curproxy->conf.logformat_string != default_tcp_log_format &&
2704 curproxy->conf.logformat_string != clf_http_log_format)
2705 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2706
2707 if (defproxy.conf.lfs_file) {
2708 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2709 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2710 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002711 }
2712
2713 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002714 curproxy->timeout.connect = defproxy.timeout.connect;
2715 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002716 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002717 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002718 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002719 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002720 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002721 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002722 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002723 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002724 }
2725
Willy Tarreaubaaee002006-06-26 02:48:02 +02002726 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002727 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002728
2729 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002730 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002731 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002732 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002733 LIST_INIT(&node->list);
2734 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2735 }
2736
Willy Tarreau62a61232013-04-12 18:13:46 +02002737 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2738 if (curproxy->conf.uniqueid_format_string)
2739 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2740
Willy Tarreau094af4e2015-01-07 15:03:42 +01002741 if (defproxy.log_tag)
2742 curproxy->log_tag = strdup(defproxy.log_tag);
2743
Willy Tarreau62a61232013-04-12 18:13:46 +02002744 if (defproxy.conf.uif_file) {
2745 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2746 curproxy->conf.uif_line = defproxy.conf.uif_line;
2747 }
William Lallemanda73203e2012-03-12 12:48:57 +01002748
2749 /* copy default header unique id */
2750 if (defproxy.header_unique_id)
2751 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2752
William Lallemand82fe75c2012-10-23 10:25:10 +02002753 /* default compression options */
2754 if (defproxy.comp != NULL) {
2755 curproxy->comp = calloc(1, sizeof(struct comp));
2756 curproxy->comp->algos = defproxy.comp->algos;
2757 curproxy->comp->types = defproxy.comp->types;
2758 }
2759
Willy Tarreaubaaee002006-06-26 02:48:02 +02002760 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002761 curproxy->conf.used_listener_id = EB_ROOT;
2762 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002763
Simon Horman98637e52014-06-20 12:30:16 +09002764 if (defproxy.check_path)
2765 curproxy->check_path = strdup(defproxy.check_path);
2766 if (defproxy.check_command)
2767 curproxy->check_command = strdup(defproxy.check_command);
2768
Simon Horman9dc49962015-01-30 11:22:59 +09002769 if (defproxy.email_alert.mailers.name)
2770 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2771 if (defproxy.email_alert.from)
2772 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2773 if (defproxy.email_alert.to)
2774 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2775 if (defproxy.email_alert.myhostname)
2776 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09002777 curproxy->email_alert.level = defproxy.email_alert.level;
Simon Horman9dc49962015-01-30 11:22:59 +09002778
Willy Tarreau93893792009-07-23 13:19:11 +02002779 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002780 }
2781 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2782 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002783 /* FIXME-20070101: we should do this too at the end of the
2784 * config parsing to free all default values.
2785 */
William Lallemand6e62fb62015-04-28 16:55:23 +02002786 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2787 err_code |= ERR_ABORT;
2788 goto out;
2789 }
2790
Willy Tarreaua534fea2008-08-03 12:19:50 +02002791 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002792 free(defproxy.check_command);
2793 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002794 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002795 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002796 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002797 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002798 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002799 free(defproxy.capture_name);
2800 free(defproxy.monitor_uri);
2801 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002802 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002803 free(defproxy.fwdfor_hdr_name);
2804 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002805 free(defproxy.orgto_hdr_name);
2806 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002807 free(defproxy.server_id_hdr_name);
2808 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002809 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002810 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002811 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002812 free(defproxy.expect_regex);
2813 defproxy.expect_regex = NULL;
2814 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002815
Willy Tarreau62a61232013-04-12 18:13:46 +02002816 if (defproxy.conf.logformat_string != default_http_log_format &&
2817 defproxy.conf.logformat_string != default_tcp_log_format &&
2818 defproxy.conf.logformat_string != clf_http_log_format)
2819 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002820
Willy Tarreau62a61232013-04-12 18:13:46 +02002821 free(defproxy.conf.uniqueid_format_string);
2822 free(defproxy.conf.lfs_file);
2823 free(defproxy.conf.uif_file);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002824 free(defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09002825 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02002826
Willy Tarreaua534fea2008-08-03 12:19:50 +02002827 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002828 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002829
Willy Tarreaubaaee002006-06-26 02:48:02 +02002830 /* we cannot free uri_auth because it might already be used */
2831 init_default_instance();
2832 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002833 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2834 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002835 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002836 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002837 }
2838 else if (curproxy == NULL) {
2839 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002840 err_code |= ERR_ALERT | ERR_FATAL;
2841 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002842 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002843
2844 /* update the current file and line being parsed */
2845 curproxy->conf.args.file = curproxy->conf.file;
2846 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002847
2848 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002849 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2850 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2851 if (err_code & ERR_FATAL)
2852 goto out;
2853 }
2854 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002855 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002856 int cur_arg;
2857
Willy Tarreaubaaee002006-06-26 02:48:02 +02002858 if (curproxy == &defproxy) {
2859 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002860 err_code |= ERR_ALERT | ERR_FATAL;
2861 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002862 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002863 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002864 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002865
Willy Tarreau24709282013-03-10 21:32:12 +01002866 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002867 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002868 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002869 err_code |= ERR_ALERT | ERR_FATAL;
2870 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002871 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002872
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002873 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002874
2875 /* use default settings for unix sockets */
2876 bind_conf->ux.uid = global.unix_bind.ux.uid;
2877 bind_conf->ux.gid = global.unix_bind.ux.gid;
2878 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002879
2880 /* NOTE: the following line might create several listeners if there
2881 * are comma-separated IPs or port ranges. So all further processing
2882 * will have to be applied to all listeners created after last_listen.
2883 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002884 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2885 if (errmsg && *errmsg) {
2886 indent_msg(&errmsg, 2);
2887 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002888 }
2889 else
2890 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2891 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002892 err_code |= ERR_ALERT | ERR_FATAL;
2893 goto out;
2894 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002895
Willy Tarreau4348fad2012-09-20 16:48:07 +02002896 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2897 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002898 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002899 }
2900
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002901 cur_arg = 2;
2902 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002903 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002904 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002905 char *err;
2906
Willy Tarreau26982662012-09-12 23:17:10 +02002907 kw = bind_find_kw(args[cur_arg]);
2908 if (kw) {
2909 char *err = NULL;
2910 int code;
2911
2912 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002913 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2914 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002915 cur_arg += 1 + kw->skip ;
2916 err_code |= ERR_ALERT | ERR_FATAL;
2917 goto out;
2918 }
2919
Willy Tarreau4348fad2012-09-20 16:48:07 +02002920 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002921 err_code |= code;
2922
2923 if (code) {
2924 if (err && *err) {
2925 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002926 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002927 }
2928 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002929 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2930 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002931 if (code & ERR_FATAL) {
2932 free(err);
2933 cur_arg += 1 + kw->skip;
2934 goto out;
2935 }
2936 }
2937 free(err);
2938 cur_arg += 1 + kw->skip;
2939 continue;
2940 }
2941
Willy Tarreau8638f482012-09-18 18:01:17 +02002942 err = NULL;
2943 if (!bind_dumped) {
2944 bind_dump_kws(&err);
2945 indent_msg(&err, 4);
2946 bind_dumped = 1;
2947 }
2948
2949 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2950 file, linenum, args[0], args[1], args[cur_arg],
2951 err ? " Registered keywords :" : "", err ? err : "");
2952 free(err);
2953
Willy Tarreau93893792009-07-23 13:19:11 +02002954 err_code |= ERR_ALERT | ERR_FATAL;
2955 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002956 }
Willy Tarreau93893792009-07-23 13:19:11 +02002957 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002958 }
2959 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002960 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002961 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2962 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002963 err_code |= ERR_ALERT | ERR_FATAL;
2964 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002965 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002966 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002967 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002968
Willy Tarreaubaaee002006-06-26 02:48:02 +02002969 /* flush useless bits */
2970 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002971 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002972 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002973 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002974 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002975 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002976
William Lallemanddf1425a2015-04-28 20:17:49 +02002977 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2978 goto out;
2979
Willy Tarreau1c47f852006-07-09 08:22:27 +02002980 if (!*args[1]) {
2981 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2982 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002983 err_code |= ERR_ALERT | ERR_FATAL;
2984 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002985 }
2986
Willy Tarreaua534fea2008-08-03 12:19:50 +02002987 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002988 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002989 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002990 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002991 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2992
Willy Tarreau93893792009-07-23 13:19:11 +02002993 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002994 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002995 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
William Lallemanddf1425a2015-04-28 20:17:49 +02002996 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2997 goto out;
2998
Willy Tarreaubaaee002006-06-26 02:48:02 +02002999 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
3000 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
3001 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
3002 else {
3003 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003004 err_code |= ERR_ALERT | ERR_FATAL;
3005 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003006 }
3007 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003008 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003009 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003010
3011 if (curproxy == &defproxy) {
3012 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3013 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003014 err_code |= ERR_ALERT | ERR_FATAL;
3015 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003016 }
3017
William Lallemanddf1425a2015-04-28 20:17:49 +02003018 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3019 goto out;
3020
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003021 if (!*args[1]) {
3022 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3023 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003024 err_code |= ERR_ALERT | ERR_FATAL;
3025 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003026 }
3027
3028 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003029 curproxy->conf.id.key = curproxy->uuid;
Willy Tarreau0d1fdf72015-05-27 16:44:02 +02003030 curproxy->options |= PR_O_FORCED_ID;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003031
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003032 if (curproxy->uuid <= 0) {
3033 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003034 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003035 err_code |= ERR_ALERT | ERR_FATAL;
3036 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003037 }
3038
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003039 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
3040 if (node) {
3041 struct proxy *target = container_of(node, struct proxy, conf.id);
3042 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
3043 file, linenum, proxy_type_str(curproxy), curproxy->id,
3044 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
3045 err_code |= ERR_ALERT | ERR_FATAL;
3046 goto out;
3047 }
3048 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003049 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003050 else if (!strcmp(args[0], "description")) {
3051 int i, len=0;
3052 char *d;
3053
Cyril Bonté99ed3272010-01-24 23:29:44 +01003054 if (curproxy == &defproxy) {
3055 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3056 file, linenum, args[0]);
3057 err_code |= ERR_ALERT | ERR_FATAL;
3058 goto out;
3059 }
3060
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003061 if (!*args[1]) {
3062 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
3063 file, linenum, args[0]);
3064 return -1;
3065 }
3066
Willy Tarreau348acfe2014-04-14 15:00:39 +02003067 for (i = 1; *args[i]; i++)
3068 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003069
3070 d = (char *)calloc(1, len);
3071 curproxy->desc = d;
3072
Willy Tarreau348acfe2014-04-14 15:00:39 +02003073 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
3074 for (i = 2; *args[i]; i++)
3075 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003076
3077 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003078 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
William Lallemanddf1425a2015-04-28 20:17:49 +02003079 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3080 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003081 curproxy->state = PR_STSTOPPED;
3082 }
3083 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
William Lallemanddf1425a2015-04-28 20:17:49 +02003084 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3085 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003086 curproxy->state = PR_STNEW;
3087 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003088 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
3089 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003090 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003091
3092 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003093 unsigned int low, high;
3094
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003095 if (strcmp(args[cur_arg], "all") == 0) {
3096 set = 0;
3097 break;
3098 }
3099 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003100 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003101 }
3102 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003103 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003104 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01003105 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003106 char *dash = strchr(args[cur_arg], '-');
3107
3108 low = high = str2uic(args[cur_arg]);
3109 if (dash)
3110 high = str2uic(dash + 1);
3111
3112 if (high < low) {
3113 unsigned int swap = low;
3114 low = high;
3115 high = swap;
3116 }
3117
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003118 if (low < 1 || high > LONGBITS) {
3119 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
3120 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02003121 err_code |= ERR_ALERT | ERR_FATAL;
3122 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003123 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01003124 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003125 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003126 }
3127 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003128 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
3129 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003130 err_code |= ERR_ALERT | ERR_FATAL;
3131 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003132 }
3133 cur_arg++;
3134 }
3135 curproxy->bind_proc = set;
3136 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003137 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02003138 if (curproxy == &defproxy) {
3139 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003140 err_code |= ERR_ALERT | ERR_FATAL;
3141 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003142 }
3143
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003144 err = invalid_char(args[1]);
3145 if (err) {
3146 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
3147 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003148 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003149 }
3150
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01003151 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003152 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
3153 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003154 err_code |= ERR_ALERT | ERR_FATAL;
3155 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003156 }
3157 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003158 else if (!strcmp(args[0], "cookie")) { /* cookie name */
3159 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003160
Willy Tarreau977b8e42006-12-29 14:19:17 +01003161 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003162 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003163
Willy Tarreaubaaee002006-06-26 02:48:02 +02003164 if (*(args[1]) == 0) {
3165 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
3166 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003167 err_code |= ERR_ALERT | ERR_FATAL;
3168 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003169 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003170
Willy Tarreau67402132012-05-31 20:40:20 +02003171 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003172 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01003173 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003174 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003175 curproxy->cookie_name = strdup(args[1]);
3176 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003177
Willy Tarreaubaaee002006-06-26 02:48:02 +02003178 cur_arg = 2;
3179 while (*(args[cur_arg])) {
3180 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003181 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003182 }
3183 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003184 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003185 }
3186 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003187 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003188 }
3189 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003190 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003191 }
3192 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003193 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003194 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003195 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003196 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003197 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003198 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003199 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003200 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02003201 else if (!strcmp(args[cur_arg], "httponly")) {
3202 curproxy->ck_opts |= PR_CK_HTTPONLY;
3203 }
3204 else if (!strcmp(args[cur_arg], "secure")) {
3205 curproxy->ck_opts |= PR_CK_SECURE;
3206 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003207 else if (!strcmp(args[cur_arg], "domain")) {
3208 if (!*args[cur_arg + 1]) {
3209 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
3210 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003211 err_code |= ERR_ALERT | ERR_FATAL;
3212 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003213 }
3214
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003215 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003216 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003217 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
3218 " dots nor does not start with a dot."
3219 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003220 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003221 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003222 }
3223
3224 err = invalid_domainchar(args[cur_arg + 1]);
3225 if (err) {
3226 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
3227 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003228 err_code |= ERR_ALERT | ERR_FATAL;
3229 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003230 }
3231
Willy Tarreau68a897b2009-12-03 23:28:34 +01003232 if (!curproxy->cookie_domain) {
3233 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
3234 } else {
3235 /* one domain was already specified, add another one by
3236 * building the string which will be returned along with
3237 * the cookie.
3238 */
3239 char *new_ptr;
3240 int new_len = strlen(curproxy->cookie_domain) +
3241 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
3242 new_ptr = malloc(new_len);
3243 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
3244 free(curproxy->cookie_domain);
3245 curproxy->cookie_domain = new_ptr;
3246 }
Willy Tarreau31936852010-10-06 16:59:56 +02003247 cur_arg++;
3248 }
3249 else if (!strcmp(args[cur_arg], "maxidle")) {
3250 unsigned int maxidle;
3251 const char *res;
3252
3253 if (!*args[cur_arg + 1]) {
3254 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
3255 file, linenum, args[cur_arg]);
3256 err_code |= ERR_ALERT | ERR_FATAL;
3257 goto out;
3258 }
3259
3260 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
3261 if (res) {
3262 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3263 file, linenum, *res, args[cur_arg]);
3264 err_code |= ERR_ALERT | ERR_FATAL;
3265 goto out;
3266 }
3267 curproxy->cookie_maxidle = maxidle;
3268 cur_arg++;
3269 }
3270 else if (!strcmp(args[cur_arg], "maxlife")) {
3271 unsigned int maxlife;
3272 const char *res;
3273
3274 if (!*args[cur_arg + 1]) {
3275 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
3276 file, linenum, args[cur_arg]);
3277 err_code |= ERR_ALERT | ERR_FATAL;
3278 goto out;
3279 }
3280
3281 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
3282 if (res) {
3283 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3284 file, linenum, *res, args[cur_arg]);
3285 err_code |= ERR_ALERT | ERR_FATAL;
3286 goto out;
3287 }
3288 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003289 cur_arg++;
3290 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003291 else {
Willy Tarreau31936852010-10-06 16:59:56 +02003292 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 +02003293 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003294 err_code |= ERR_ALERT | ERR_FATAL;
3295 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003296 }
3297 cur_arg++;
3298 }
Willy Tarreau67402132012-05-31 20:40:20 +02003299 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003300 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
3301 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003302 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003303 }
3304
Willy Tarreau67402132012-05-31 20:40:20 +02003305 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003306 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
3307 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003308 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003309 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003310
Willy Tarreau67402132012-05-31 20:40:20 +02003311 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003312 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
3313 file, linenum);
3314 err_code |= ERR_ALERT | ERR_FATAL;
3315 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003316 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09003317 else if (!strcmp(args[0], "email-alert")) {
3318 if (*(args[1]) == 0) {
3319 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3320 file, linenum, args[0]);
3321 err_code |= ERR_ALERT | ERR_FATAL;
3322 goto out;
3323 }
3324
3325 if (!strcmp(args[1], "from")) {
3326 if (*(args[1]) == 0) {
3327 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3328 file, linenum, args[1]);
3329 err_code |= ERR_ALERT | ERR_FATAL;
3330 goto out;
3331 }
3332 free(curproxy->email_alert.from);
3333 curproxy->email_alert.from = strdup(args[2]);
3334 }
3335 else if (!strcmp(args[1], "mailers")) {
3336 if (*(args[1]) == 0) {
3337 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3338 file, linenum, args[1]);
3339 err_code |= ERR_ALERT | ERR_FATAL;
3340 goto out;
3341 }
3342 free(curproxy->email_alert.mailers.name);
3343 curproxy->email_alert.mailers.name = strdup(args[2]);
3344 }
3345 else if (!strcmp(args[1], "myhostname")) {
3346 if (*(args[1]) == 0) {
3347 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3348 file, linenum, args[1]);
3349 err_code |= ERR_ALERT | ERR_FATAL;
3350 goto out;
3351 }
3352 free(curproxy->email_alert.myhostname);
3353 curproxy->email_alert.myhostname = strdup(args[2]);
3354 }
Simon Horman64e34162015-02-06 11:11:57 +09003355 else if (!strcmp(args[1], "level")) {
3356 curproxy->email_alert.level = get_log_level(args[2]);
3357 if (curproxy->email_alert.level < 0) {
3358 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
3359 file, linenum, args[1], args[2]);
3360 err_code |= ERR_ALERT | ERR_FATAL;
3361 goto out;
3362 }
3363 }
Simon Horman9dc49962015-01-30 11:22:59 +09003364 else if (!strcmp(args[1], "to")) {
3365 if (*(args[1]) == 0) {
3366 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3367 file, linenum, args[1]);
3368 err_code |= ERR_ALERT | ERR_FATAL;
3369 goto out;
3370 }
3371 free(curproxy->email_alert.to);
3372 curproxy->email_alert.to = strdup(args[2]);
3373 }
3374 else {
3375 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
3376 file, linenum, args[1]);
3377 err_code |= ERR_ALERT | ERR_FATAL;
3378 goto out;
3379 }
Simon Horman64e34162015-02-06 11:11:57 +09003380 /* Indicate that the email_alert is at least partially configured */
3381 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09003382 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09003383 else if (!strcmp(args[0], "external-check")) {
3384 if (*(args[1]) == 0) {
3385 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3386 file, linenum, args[0]);
3387 err_code |= ERR_ALERT | ERR_FATAL;
3388 goto out;
3389 }
3390
3391 if (!strcmp(args[1], "command")) {
William Lallemanddf1425a2015-04-28 20:17:49 +02003392 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3393 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09003394 if (*(args[1]) == 0) {
3395 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3396 file, linenum, args[1]);
3397 err_code |= ERR_ALERT | ERR_FATAL;
3398 goto out;
3399 }
3400 free(curproxy->check_command);
3401 curproxy->check_command = strdup(args[2]);
3402 }
3403 else if (!strcmp(args[1], "path")) {
William Lallemanddf1425a2015-04-28 20:17:49 +02003404 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3405 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09003406 if (*(args[1]) == 0) {
3407 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3408 file, linenum, args[1]);
3409 err_code |= ERR_ALERT | ERR_FATAL;
3410 goto out;
3411 }
3412 free(curproxy->check_path);
3413 curproxy->check_path = strdup(args[2]);
3414 }
3415 else {
3416 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
3417 file, linenum, args[1]);
3418 err_code |= ERR_ALERT | ERR_FATAL;
3419 goto out;
3420 }
3421 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02003422 else if (!strcmp(args[0], "persist")) { /* persist */
3423 if (*(args[1]) == 0) {
3424 Alert("parsing [%s:%d] : missing persist method.\n",
3425 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003426 err_code |= ERR_ALERT | ERR_FATAL;
3427 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003428 }
3429
3430 if (!strncmp(args[1], "rdp-cookie", 10)) {
3431 curproxy->options2 |= PR_O2_RDPC_PRST;
3432
Emeric Brunb982a3d2010-01-04 15:45:53 +01003433 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003434 const char *beg, *end;
3435
3436 beg = args[1] + 11;
3437 end = strchr(beg, ')');
3438
William Lallemanddf1425a2015-04-28 20:17:49 +02003439 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3440 goto out;
3441
Emeric Brun647caf12009-06-30 17:57:00 +02003442 if (!end || end == beg) {
3443 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3444 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003445 err_code |= ERR_ALERT | ERR_FATAL;
3446 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003447 }
3448
3449 free(curproxy->rdp_cookie_name);
3450 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3451 curproxy->rdp_cookie_len = end-beg;
3452 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003453 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003454 free(curproxy->rdp_cookie_name);
3455 curproxy->rdp_cookie_name = strdup("msts");
3456 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3457 }
3458 else { /* syntax */
3459 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3460 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003461 err_code |= ERR_ALERT | ERR_FATAL;
3462 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003463 }
3464 }
3465 else {
3466 Alert("parsing [%s:%d] : unknown persist method.\n",
3467 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003468 err_code |= ERR_ALERT | ERR_FATAL;
3469 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003470 }
3471 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003472 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreau6db62c52015-08-10 19:04:29 +02003473 Alert("parsing [%s:%d] : '%s' is not supported anymore, please check the documentation.\n", file, linenum, args[0]);
3474 err_code |= ERR_ALERT | ERR_FATAL;
3475 goto out;
3476 }
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02003477 else if (!strcmp(args[0], "load-server-state-from-file")) {
3478 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3479 err_code |= ERR_WARN;
3480 if (!strcmp(args[1], "global")) { /* use the file pointed to by global server-state-file directive */
3481 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_GLOBAL;
3482 }
3483 else if (!strcmp(args[1], "local")) { /* use the server-state-file-name variable to locate the server-state file */
3484 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_LOCAL;
3485 }
3486 else if (!strcmp(args[1], "none")) { /* don't use server-state-file directive for this backend */
3487 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
3488 }
3489 else {
3490 Alert("parsing [%s:%d] : '%s' expects 'global', 'local' or 'none'. Got '%s'\n",
3491 file, linenum, args[0], args[1]);
3492 err_code |= ERR_ALERT | ERR_FATAL;
3493 goto out;
3494 }
3495 }
3496 else if (!strcmp(args[0], "server-state-file-name")) {
3497 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3498 err_code |= ERR_WARN;
3499 if (*(args[1]) == 0) {
3500 Alert("parsing [%s:%d] : '%s' expects 'use-backend-name' or a string. Got no argument\n",
3501 file, linenum, args[0]);
3502 err_code |= ERR_ALERT | ERR_FATAL;
3503 goto out;
3504 }
3505 else if (!strcmp(args[1], "use-backend-name"))
3506 curproxy->server_state_file_name = strdup(curproxy->id);
3507 else
3508 curproxy->server_state_file_name = strdup(args[1]);
3509 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003510 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003511 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003512 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003513
Willy Tarreaubaaee002006-06-26 02:48:02 +02003514 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003515 if (curproxy == &defproxy) {
3516 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3517 err_code |= ERR_ALERT | ERR_FATAL;
3518 goto out;
3519 }
3520
William Lallemand1a748ae2015-05-19 16:37:23 +02003521 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3522 goto out;
3523
Willy Tarreaubaaee002006-06-26 02:48:02 +02003524 if (*(args[4]) == 0) {
3525 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3526 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003527 err_code |= ERR_ALERT | ERR_FATAL;
3528 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003529 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003530 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003531 curproxy->capture_name = strdup(args[2]);
3532 curproxy->capture_namelen = strlen(curproxy->capture_name);
3533 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003534 curproxy->to_log |= LW_COOKIE;
3535 }
3536 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3537 struct cap_hdr *hdr;
3538
3539 if (curproxy == &defproxy) {
3540 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 +02003541 err_code |= ERR_ALERT | ERR_FATAL;
3542 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003543 }
3544
William Lallemand1a748ae2015-05-19 16:37:23 +02003545 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3546 goto out;
3547
Willy Tarreaubaaee002006-06-26 02:48:02 +02003548 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3549 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3550 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003551 err_code |= ERR_ALERT | ERR_FATAL;
3552 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003553 }
3554
3555 hdr = calloc(sizeof(struct cap_hdr), 1);
3556 hdr->next = curproxy->req_cap;
3557 hdr->name = strdup(args[3]);
3558 hdr->namelen = strlen(args[3]);
3559 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003560 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003561 hdr->index = curproxy->nb_req_cap++;
3562 curproxy->req_cap = hdr;
3563 curproxy->to_log |= LW_REQHDR;
3564 }
3565 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3566 struct cap_hdr *hdr;
3567
3568 if (curproxy == &defproxy) {
3569 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 +02003570 err_code |= ERR_ALERT | ERR_FATAL;
3571 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003572 }
3573
William Lallemand1a748ae2015-05-19 16:37:23 +02003574 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3575 goto out;
3576
Willy Tarreaubaaee002006-06-26 02:48:02 +02003577 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3578 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3579 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003580 err_code |= ERR_ALERT | ERR_FATAL;
3581 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003582 }
3583 hdr = calloc(sizeof(struct cap_hdr), 1);
3584 hdr->next = curproxy->rsp_cap;
3585 hdr->name = strdup(args[3]);
3586 hdr->namelen = strlen(args[3]);
3587 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003588 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003589 hdr->index = curproxy->nb_rsp_cap++;
3590 curproxy->rsp_cap = hdr;
3591 curproxy->to_log |= LW_RSPHDR;
3592 }
3593 else {
3594 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3595 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003596 err_code |= ERR_ALERT | ERR_FATAL;
3597 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003598 }
3599 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003600 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003601 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003602 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003603
William Lallemanddf1425a2015-04-28 20:17:49 +02003604 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3605 goto out;
3606
Willy Tarreaubaaee002006-06-26 02:48:02 +02003607 if (*(args[1]) == 0) {
3608 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3609 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003610 err_code |= ERR_ALERT | ERR_FATAL;
3611 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003612 }
3613 curproxy->conn_retries = atol(args[1]);
3614 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003615 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003616 struct act_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003617
3618 if (curproxy == &defproxy) {
3619 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3620 err_code |= ERR_ALERT | ERR_FATAL;
3621 goto out;
3622 }
3623
Willy Tarreau20b0de52012-12-24 15:45:22 +01003624 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003625 !LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003626 (LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3627 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_DENY ||
3628 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REDIR ||
3629 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REQ_AUTH)) {
Willy Tarreau20b0de52012-12-24 15:45:22 +01003630 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 +01003631 file, linenum, args[0]);
3632 err_code |= ERR_WARN;
3633 }
3634
Willy Tarreauff011f22011-01-06 17:51:27 +01003635 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003636
Willy Tarreauff011f22011-01-06 17:51:27 +01003637 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003638 err_code |= ERR_ALERT | ERR_ABORT;
3639 goto out;
3640 }
3641
Willy Tarreau5002f572014-04-23 01:32:02 +02003642 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003643 err_code |= warnif_cond_conflicts(rule->cond,
3644 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3645 file, linenum);
3646
Willy Tarreauff011f22011-01-06 17:51:27 +01003647 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003648 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003649 else if (!strcmp(args[0], "http-response")) { /* response access control */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003650 struct act_rule *rule;
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003651
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
3658 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003659 !LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003660 (LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3661 LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_DENY)) {
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003662 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3663 file, linenum, args[0]);
3664 err_code |= ERR_WARN;
3665 }
3666
3667 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3668
3669 if (!rule) {
3670 err_code |= ERR_ALERT | ERR_ABORT;
3671 goto out;
3672 }
3673
3674 err_code |= warnif_cond_conflicts(rule->cond,
3675 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3676 file, linenum);
3677
3678 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3679 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003680 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3681 /* set the header name and length into the proxy structure */
3682 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3683 err_code |= ERR_WARN;
3684
3685 if (!*args[1]) {
3686 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3687 file, linenum, args[0]);
3688 err_code |= ERR_ALERT | ERR_FATAL;
3689 goto out;
3690 }
3691
3692 /* set the desired header name */
3693 free(curproxy->server_id_hdr_name);
3694 curproxy->server_id_hdr_name = strdup(args[1]);
3695 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3696 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003697 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003698 struct act_rule *rule;
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003699
Willy Tarreaub099aca2008-10-12 17:26:37 +02003700 if (curproxy == &defproxy) {
3701 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003702 err_code |= ERR_ALERT | ERR_FATAL;
3703 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003704 }
3705
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003706 /* emulate "block" using "http-request block". Since these rules are supposed to
3707 * be processed before all http-request rules, we put them into their own list
3708 * and will insert them at the end.
3709 */
3710 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3711 if (!rule) {
3712 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003713 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003714 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003715 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3716 err_code |= warnif_cond_conflicts(rule->cond,
3717 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3718 file, linenum);
3719 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003720
3721 if (!already_warned(WARN_BLOCK_DEPRECATED))
3722 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]);
3723
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003724 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003725 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003726 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003727
Cyril Bonté99ed3272010-01-24 23:29:44 +01003728 if (curproxy == &defproxy) {
3729 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3730 err_code |= ERR_ALERT | ERR_FATAL;
3731 goto out;
3732 }
3733
Willy Tarreaube4653b2015-05-28 15:26:58 +02003734 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003735 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3736 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003737 err_code |= ERR_ALERT | ERR_FATAL;
3738 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003739 }
3740
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003741 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003742 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003743 err_code |= warnif_cond_conflicts(rule->cond,
3744 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3745 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003746 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003747 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003748 struct switching_rule *rule;
3749
Willy Tarreaub099aca2008-10-12 17:26:37 +02003750 if (curproxy == &defproxy) {
3751 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003752 err_code |= ERR_ALERT | ERR_FATAL;
3753 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003754 }
3755
Willy Tarreau55ea7572007-06-17 19:56:27 +02003756 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003757 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003758
3759 if (*(args[1]) == 0) {
3760 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003761 err_code |= ERR_ALERT | ERR_FATAL;
3762 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003763 }
3764
Willy Tarreauf51658d2014-04-23 01:21:56 +02003765 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3766 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3767 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3768 file, linenum, errmsg);
3769 err_code |= ERR_ALERT | ERR_FATAL;
3770 goto out;
3771 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003772
Willy Tarreauf51658d2014-04-23 01:21:56 +02003773 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003774 }
3775
3776 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
3777 rule->cond = cond;
3778 rule->be.name = strdup(args[1]);
3779 LIST_INIT(&rule->list);
3780 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3781 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003782 else if (strcmp(args[0], "use-server") == 0) {
3783 struct server_rule *rule;
3784
3785 if (curproxy == &defproxy) {
3786 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3787 err_code |= ERR_ALERT | ERR_FATAL;
3788 goto out;
3789 }
3790
3791 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3792 err_code |= ERR_WARN;
3793
3794 if (*(args[1]) == 0) {
3795 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3796 err_code |= ERR_ALERT | ERR_FATAL;
3797 goto out;
3798 }
3799
3800 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3801 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3802 file, linenum, args[0]);
3803 err_code |= ERR_ALERT | ERR_FATAL;
3804 goto out;
3805 }
3806
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003807 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3808 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3809 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003810 err_code |= ERR_ALERT | ERR_FATAL;
3811 goto out;
3812 }
3813
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003814 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003815
3816 rule = (struct server_rule *)calloc(1, sizeof(*rule));
3817 rule->cond = cond;
3818 rule->srv.name = strdup(args[1]);
3819 LIST_INIT(&rule->list);
3820 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3821 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3822 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003823 else if ((!strcmp(args[0], "force-persist")) ||
3824 (!strcmp(args[0], "ignore-persist"))) {
3825 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003826
3827 if (curproxy == &defproxy) {
3828 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3829 err_code |= ERR_ALERT | ERR_FATAL;
3830 goto out;
3831 }
3832
3833 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3834 err_code |= ERR_WARN;
3835
Willy Tarreauef6494c2010-01-28 17:12:36 +01003836 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003837 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3838 file, linenum, args[0]);
3839 err_code |= ERR_ALERT | ERR_FATAL;
3840 goto out;
3841 }
3842
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003843 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3844 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3845 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003846 err_code |= ERR_ALERT | ERR_FATAL;
3847 goto out;
3848 }
3849
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003850 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3851 * where force-persist is applied.
3852 */
3853 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003854
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003855 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003856 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003857 if (!strcmp(args[0], "force-persist")) {
3858 rule->type = PERSIST_TYPE_FORCE;
3859 } else {
3860 rule->type = PERSIST_TYPE_IGNORE;
3861 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003862 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003863 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003864 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003865 else if (!strcmp(args[0], "stick-table")) {
3866 int myidx = 1;
Willy Tarreaue45288c2015-05-26 10:49:46 +02003867 struct proxy *other;
3868
Willy Tarreaue2dc1fa2015-05-26 12:08:07 +02003869 other = proxy_tbl_by_name(curproxy->id);
Willy Tarreaue45288c2015-05-26 10:49:46 +02003870 if (other) {
3871 Alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
3872 file, linenum, curproxy->id, proxy_type_str(other), other->id, other->conf.file, other->conf.line);
3873 err_code |= ERR_ALERT | ERR_FATAL;
3874 goto out;
3875 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003876
Emeric Brun32da3c42010-09-23 18:39:19 +02003877 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003878 curproxy->table.type = (unsigned int)-1;
3879 while (*args[myidx]) {
3880 const char *err;
3881
3882 if (strcmp(args[myidx], "size") == 0) {
3883 myidx++;
3884 if (!*(args[myidx])) {
3885 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3886 file, linenum, args[myidx-1]);
3887 err_code |= ERR_ALERT | ERR_FATAL;
3888 goto out;
3889 }
3890 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3891 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3892 file, linenum, *err, args[myidx-1]);
3893 err_code |= ERR_ALERT | ERR_FATAL;
3894 goto out;
3895 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003896 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003897 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003898 else if (strcmp(args[myidx], "peers") == 0) {
3899 myidx++;
Godbach50523162013-12-11 19:48:57 +08003900 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003901 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3902 file, linenum, args[myidx-1]);
3903 err_code |= ERR_ALERT | ERR_FATAL;
3904 goto out;
Godbach50523162013-12-11 19:48:57 +08003905 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003906 curproxy->table.peers.name = strdup(args[myidx++]);
3907 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003908 else if (strcmp(args[myidx], "expire") == 0) {
3909 myidx++;
3910 if (!*(args[myidx])) {
3911 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3912 file, linenum, args[myidx-1]);
3913 err_code |= ERR_ALERT | ERR_FATAL;
3914 goto out;
3915 }
3916 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3917 if (err) {
3918 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3919 file, linenum, *err, args[myidx-1]);
3920 err_code |= ERR_ALERT | ERR_FATAL;
3921 goto out;
3922 }
3923 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003924 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003925 }
3926 else if (strcmp(args[myidx], "nopurge") == 0) {
3927 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003928 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003929 }
3930 else if (strcmp(args[myidx], "type") == 0) {
3931 myidx++;
3932 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3933 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3934 file, linenum, args[myidx]);
3935 err_code |= ERR_ALERT | ERR_FATAL;
3936 goto out;
3937 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003938 /* myidx already points to next arg */
3939 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003940 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003941 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003942 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003943
3944 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003945 nw = args[myidx];
3946 while (*nw) {
3947 /* the "store" keyword supports a comma-separated list */
3948 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003949 sa = NULL; /* store arg */
3950 while (*nw && *nw != ',') {
3951 if (*nw == '(') {
3952 *nw = 0;
3953 sa = ++nw;
3954 while (*nw != ')') {
3955 if (!*nw) {
3956 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3957 file, linenum, args[0], cw);
3958 err_code |= ERR_ALERT | ERR_FATAL;
3959 goto out;
3960 }
3961 nw++;
3962 }
3963 *nw = '\0';
3964 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003965 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003966 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003967 if (*nw)
3968 *nw++ = '\0';
3969 type = stktable_get_data_type(cw);
3970 if (type < 0) {
3971 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3972 file, linenum, args[0], cw);
3973 err_code |= ERR_ALERT | ERR_FATAL;
3974 goto out;
3975 }
Willy Tarreauac782882010-06-20 10:41:54 +02003976
3977 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3978 switch (err) {
3979 case PE_NONE: break;
3980 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003981 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3982 file, linenum, args[0], cw);
3983 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003984 break;
3985
3986 case PE_ARG_MISSING:
3987 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3988 file, linenum, args[0], cw);
3989 err_code |= ERR_ALERT | ERR_FATAL;
3990 goto out;
3991
3992 case PE_ARG_NOT_USED:
3993 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3994 file, linenum, args[0], cw);
3995 err_code |= ERR_ALERT | ERR_FATAL;
3996 goto out;
3997
3998 default:
3999 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
4000 file, linenum, args[0], cw);
4001 err_code |= ERR_ALERT | ERR_FATAL;
4002 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004003 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004004 }
4005 myidx++;
4006 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004007 else {
4008 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
4009 file, linenum, args[myidx]);
4010 err_code |= ERR_ALERT | ERR_FATAL;
4011 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004012 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004013 }
4014
4015 if (!curproxy->table.size) {
4016 Alert("parsing [%s:%d] : stick-table: missing size.\n",
4017 file, linenum);
4018 err_code |= ERR_ALERT | ERR_FATAL;
4019 goto out;
4020 }
4021
4022 if (curproxy->table.type == (unsigned int)-1) {
4023 Alert("parsing [%s:%d] : stick-table: missing type.\n",
4024 file, linenum);
4025 err_code |= ERR_ALERT | ERR_FATAL;
4026 goto out;
4027 }
4028 }
4029 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004030 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02004031 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004032 int myidx = 0;
4033 const char *name = NULL;
4034 int flags;
4035
4036 if (curproxy == &defproxy) {
4037 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4038 err_code |= ERR_ALERT | ERR_FATAL;
4039 goto out;
4040 }
4041
4042 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
4043 err_code |= ERR_WARN;
4044 goto out;
4045 }
4046
4047 myidx++;
4048 if ((strcmp(args[myidx], "store") == 0) ||
4049 (strcmp(args[myidx], "store-request") == 0)) {
4050 myidx++;
4051 flags = STK_IS_STORE;
4052 }
4053 else if (strcmp(args[myidx], "store-response") == 0) {
4054 myidx++;
4055 flags = STK_IS_STORE | STK_ON_RSP;
4056 }
4057 else if (strcmp(args[myidx], "match") == 0) {
4058 myidx++;
4059 flags = STK_IS_MATCH;
4060 }
4061 else if (strcmp(args[myidx], "on") == 0) {
4062 myidx++;
4063 flags = STK_IS_MATCH | STK_IS_STORE;
4064 }
4065 else {
4066 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
4067 err_code |= ERR_ALERT | ERR_FATAL;
4068 goto out;
4069 }
4070
4071 if (*(args[myidx]) == 0) {
4072 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
4073 err_code |= ERR_ALERT | ERR_FATAL;
4074 goto out;
4075 }
4076
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004077 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01004078 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004079 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01004080 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004081 err_code |= ERR_ALERT | ERR_FATAL;
4082 goto out;
4083 }
4084
4085 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01004086 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
4087 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
4088 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004089 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004090 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004091 goto out;
4092 }
4093 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01004094 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
4095 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
4096 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004097 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004098 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004099 goto out;
4100 }
4101 }
4102
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004103 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01004104 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004105
Emeric Brunb982a3d2010-01-04 15:45:53 +01004106 if (strcmp(args[myidx], "table") == 0) {
4107 myidx++;
4108 name = args[myidx++];
4109 }
4110
Willy Tarreauef6494c2010-01-28 17:12:36 +01004111 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004112 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
4113 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
4114 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004115 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004116 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004117 goto out;
4118 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004119 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01004120 else if (*(args[myidx])) {
4121 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
4122 file, linenum, args[0], args[myidx]);
4123 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004124 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01004125 goto out;
4126 }
Emeric Brun97679e72010-09-23 17:56:44 +02004127 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004128 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02004129 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004130 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01004131
Emeric Brunb982a3d2010-01-04 15:45:53 +01004132 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
4133 rule->cond = cond;
4134 rule->expr = expr;
4135 rule->flags = flags;
4136 rule->table.name = name ? strdup(name) : NULL;
4137 LIST_INIT(&rule->list);
4138 if (flags & STK_ON_RSP)
4139 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
4140 else
4141 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
4142 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004143 else if (!strcmp(args[0], "stats")) {
4144 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
4145 curproxy->uri_auth = NULL; /* we must detach from the default config */
4146
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004147 if (!*args[1]) {
4148 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02004149 } else if (!strcmp(args[1], "admin")) {
4150 struct stats_admin_rule *rule;
4151
4152 if (curproxy == &defproxy) {
4153 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
4154 err_code |= ERR_ALERT | ERR_FATAL;
4155 goto out;
4156 }
4157
4158 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4159 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4160 err_code |= ERR_ALERT | ERR_ABORT;
4161 goto out;
4162 }
4163
4164 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4165 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4166 file, linenum, args[0], args[1]);
4167 err_code |= ERR_ALERT | ERR_FATAL;
4168 goto out;
4169 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004170 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4171 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
4172 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02004173 err_code |= ERR_ALERT | ERR_FATAL;
4174 goto out;
4175 }
4176
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004177 err_code |= warnif_cond_conflicts(cond,
4178 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4179 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02004180
4181 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
4182 rule->cond = cond;
4183 LIST_INIT(&rule->list);
4184 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004185 } else if (!strcmp(args[1], "uri")) {
4186 if (*(args[2]) == 0) {
4187 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004188 err_code |= ERR_ALERT | ERR_FATAL;
4189 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004190 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
4191 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004192 err_code |= ERR_ALERT | ERR_ABORT;
4193 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004194 }
4195 } else if (!strcmp(args[1], "realm")) {
4196 if (*(args[2]) == 0) {
4197 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004198 err_code |= ERR_ALERT | ERR_FATAL;
4199 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004200 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
4201 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004202 err_code |= ERR_ALERT | ERR_ABORT;
4203 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004204 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02004205 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004206 unsigned interval;
4207
4208 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
4209 if (err) {
4210 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
4211 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004212 err_code |= ERR_ALERT | ERR_FATAL;
4213 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004214 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
4215 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004216 err_code |= ERR_ALERT | ERR_ABORT;
4217 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004218 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004219 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004220 struct act_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004221
4222 if (curproxy == &defproxy) {
4223 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4224 err_code |= ERR_ALERT | ERR_FATAL;
4225 goto out;
4226 }
4227
4228 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4229 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4230 err_code |= ERR_ALERT | ERR_ABORT;
4231 goto out;
4232 }
4233
Willy Tarreauff011f22011-01-06 17:51:27 +01004234 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004235 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct act_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004236 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
4237 file, linenum, args[0]);
4238 err_code |= ERR_WARN;
4239 }
4240
Willy Tarreauff011f22011-01-06 17:51:27 +01004241 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004242
Willy Tarreauff011f22011-01-06 17:51:27 +01004243 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004244 err_code |= ERR_ALERT | ERR_ABORT;
4245 goto out;
4246 }
4247
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004248 err_code |= warnif_cond_conflicts(rule->cond,
4249 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4250 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01004251 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004252
Willy Tarreaubaaee002006-06-26 02:48:02 +02004253 } else if (!strcmp(args[1], "auth")) {
4254 if (*(args[2]) == 0) {
4255 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004256 err_code |= ERR_ALERT | ERR_FATAL;
4257 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004258 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
4259 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004260 err_code |= ERR_ALERT | ERR_ABORT;
4261 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004262 }
4263 } else if (!strcmp(args[1], "scope")) {
4264 if (*(args[2]) == 0) {
4265 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004266 err_code |= ERR_ALERT | ERR_FATAL;
4267 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004268 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
4269 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004270 err_code |= ERR_ALERT | ERR_ABORT;
4271 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004272 }
4273 } else if (!strcmp(args[1], "enable")) {
4274 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4275 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004276 err_code |= ERR_ALERT | ERR_ABORT;
4277 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004278 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004279 } else if (!strcmp(args[1], "hide-version")) {
4280 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
4281 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004282 err_code |= ERR_ALERT | ERR_ABORT;
4283 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004284 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01004285 } else if (!strcmp(args[1], "show-legends")) {
4286 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
4287 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4288 err_code |= ERR_ALERT | ERR_ABORT;
4289 goto out;
4290 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004291 } else if (!strcmp(args[1], "show-node")) {
4292
4293 if (*args[2]) {
4294 int i;
4295 char c;
4296
4297 for (i=0; args[2][i]; i++) {
4298 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01004299 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
4300 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004301 break;
4302 }
4303
4304 if (!i || args[2][i]) {
4305 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
4306 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
4307 file, linenum, args[0], args[1]);
4308 err_code |= ERR_ALERT | ERR_FATAL;
4309 goto out;
4310 }
4311 }
4312
4313 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
4314 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4315 err_code |= ERR_ALERT | ERR_ABORT;
4316 goto out;
4317 }
4318 } else if (!strcmp(args[1], "show-desc")) {
4319 char *desc = NULL;
4320
4321 if (*args[2]) {
4322 int i, len=0;
4323 char *d;
4324
Willy Tarreau348acfe2014-04-14 15:00:39 +02004325 for (i = 2; *args[i]; i++)
4326 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004327
4328 desc = d = (char *)calloc(1, len);
4329
Willy Tarreau348acfe2014-04-14 15:00:39 +02004330 d += snprintf(d, desc + len - d, "%s", args[2]);
4331 for (i = 3; *args[i]; i++)
4332 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004333 }
4334
4335 if (!*args[2] && !global.desc)
4336 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
4337 file, linenum, args[1]);
4338 else {
4339 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
4340 free(desc);
4341 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4342 err_code |= ERR_ALERT | ERR_ABORT;
4343 goto out;
4344 }
4345 free(desc);
4346 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004347 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004348stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02004349 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 +01004350 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004351 err_code |= ERR_ALERT | ERR_FATAL;
4352 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004353 }
4354 }
4355 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004356 int optnum;
4357
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004358 if (*(args[1]) == '\0') {
4359 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
4360 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004361 err_code |= ERR_ALERT | ERR_FATAL;
4362 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004363 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01004364
4365 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
4366 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004367 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
4368 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4369 file, linenum, cfg_opts[optnum].name);
4370 err_code |= ERR_ALERT | ERR_FATAL;
4371 goto out;
4372 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004373 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4374 goto out;
4375
Willy Tarreau93893792009-07-23 13:19:11 +02004376 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
4377 err_code |= ERR_WARN;
4378 goto out;
4379 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004380
Willy Tarreau3842f002009-06-14 11:39:52 +02004381 curproxy->no_options &= ~cfg_opts[optnum].val;
4382 curproxy->options &= ~cfg_opts[optnum].val;
4383
4384 switch (kwm) {
4385 case KWM_STD:
4386 curproxy->options |= cfg_opts[optnum].val;
4387 break;
4388 case KWM_NO:
4389 curproxy->no_options |= cfg_opts[optnum].val;
4390 break;
4391 case KWM_DEF: /* already cleared */
4392 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004393 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004394
Willy Tarreau93893792009-07-23 13:19:11 +02004395 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004396 }
4397 }
4398
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004399 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
4400 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004401 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
4402 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4403 file, linenum, cfg_opts2[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;
Willy Tarreau93893792009-07-23 13:19:11 +02004409 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4410 err_code |= ERR_WARN;
4411 goto out;
4412 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004413
Willy Tarreau3842f002009-06-14 11:39:52 +02004414 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4415 curproxy->options2 &= ~cfg_opts2[optnum].val;
4416
4417 switch (kwm) {
4418 case KWM_STD:
4419 curproxy->options2 |= cfg_opts2[optnum].val;
4420 break;
4421 case KWM_NO:
4422 curproxy->no_options2 |= cfg_opts2[optnum].val;
4423 break;
4424 case KWM_DEF: /* already cleared */
4425 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004426 }
Willy Tarreau93893792009-07-23 13:19:11 +02004427 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004428 }
4429 }
4430
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004431 /* HTTP options override each other. They can be cancelled using
4432 * "no option xxx" which only switches to default mode if the mode
4433 * was this one (useful for cancelling options set in defaults
4434 * sections).
4435 */
4436 if (strcmp(args[1], "httpclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004437 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4438 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004439 if (kwm == KWM_STD) {
4440 curproxy->options &= ~PR_O_HTTP_MODE;
4441 curproxy->options |= PR_O_HTTP_PCL;
4442 goto out;
4443 }
4444 else if (kwm == KWM_NO) {
4445 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4446 curproxy->options &= ~PR_O_HTTP_MODE;
4447 goto out;
4448 }
4449 }
4450 else if (strcmp(args[1], "forceclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004451 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4452 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004453 if (kwm == KWM_STD) {
4454 curproxy->options &= ~PR_O_HTTP_MODE;
4455 curproxy->options |= PR_O_HTTP_FCL;
4456 goto out;
4457 }
4458 else if (kwm == KWM_NO) {
4459 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4460 curproxy->options &= ~PR_O_HTTP_MODE;
4461 goto out;
4462 }
4463 }
4464 else if (strcmp(args[1], "http-server-close") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004465 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4466 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004467 if (kwm == KWM_STD) {
4468 curproxy->options &= ~PR_O_HTTP_MODE;
4469 curproxy->options |= PR_O_HTTP_SCL;
4470 goto out;
4471 }
4472 else if (kwm == KWM_NO) {
4473 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4474 curproxy->options &= ~PR_O_HTTP_MODE;
4475 goto out;
4476 }
4477 }
4478 else if (strcmp(args[1], "http-keep-alive") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004479 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4480 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004481 if (kwm == KWM_STD) {
4482 curproxy->options &= ~PR_O_HTTP_MODE;
4483 curproxy->options |= PR_O_HTTP_KAL;
4484 goto out;
4485 }
4486 else if (kwm == KWM_NO) {
4487 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4488 curproxy->options &= ~PR_O_HTTP_MODE;
4489 goto out;
4490 }
4491 }
4492 else if (strcmp(args[1], "http-tunnel") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004493 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4494 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004495 if (kwm == KWM_STD) {
4496 curproxy->options &= ~PR_O_HTTP_MODE;
4497 curproxy->options |= PR_O_HTTP_TUN;
4498 goto out;
4499 }
4500 else if (kwm == KWM_NO) {
4501 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4502 curproxy->options &= ~PR_O_HTTP_MODE;
4503 goto out;
4504 }
4505 }
4506
Joseph Lynch726ab712015-05-11 23:25:34 -07004507 /* Redispatch can take an integer argument that control when the
4508 * resispatch occurs. All values are relative to the retries option.
4509 * This can be cancelled using "no option xxx".
4510 */
4511 if (strcmp(args[1], "redispatch") == 0) {
4512 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
4513 err_code |= ERR_WARN;
4514 goto out;
4515 }
4516
4517 curproxy->no_options &= ~PR_O_REDISP;
4518 curproxy->options &= ~PR_O_REDISP;
4519
4520 switch (kwm) {
4521 case KWM_STD:
4522 curproxy->options |= PR_O_REDISP;
4523 curproxy->redispatch_after = -1;
4524 if(*args[2]) {
4525 curproxy->redispatch_after = atol(args[2]);
4526 }
4527 break;
4528 case KWM_NO:
4529 curproxy->no_options |= PR_O_REDISP;
4530 curproxy->redispatch_after = 0;
4531 break;
4532 case KWM_DEF: /* already cleared */
4533 break;
4534 }
4535 goto out;
4536 }
4537
Willy Tarreau3842f002009-06-14 11:39:52 +02004538 if (kwm != KWM_STD) {
4539 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004540 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004541 err_code |= ERR_ALERT | ERR_FATAL;
4542 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004543 }
4544
Emeric Brun3a058f32009-06-30 18:26:00 +02004545 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004546 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004547 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004548 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004549 if (*(args[2]) != '\0') {
4550 if (!strcmp(args[2], "clf")) {
4551 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004552 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004553 } else {
William Lallemand77063bc2015-05-28 18:02:48 +02004554 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004555 err_code |= ERR_ALERT | ERR_FATAL;
4556 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004557 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004558 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
4559 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004560 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004561 if (curproxy->conf.logformat_string != default_http_log_format &&
4562 curproxy->conf.logformat_string != default_tcp_log_format &&
4563 curproxy->conf.logformat_string != clf_http_log_format)
4564 free(curproxy->conf.logformat_string);
4565 curproxy->conf.logformat_string = logformat;
4566
4567 free(curproxy->conf.lfs_file);
4568 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4569 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004570 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004571 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004572 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004573 if (curproxy->conf.logformat_string != default_http_log_format &&
4574 curproxy->conf.logformat_string != default_tcp_log_format &&
4575 curproxy->conf.logformat_string != clf_http_log_format)
4576 free(curproxy->conf.logformat_string);
4577 curproxy->conf.logformat_string = default_tcp_log_format;
4578
4579 free(curproxy->conf.lfs_file);
4580 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4581 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemanddf1425a2015-04-28 20:17:49 +02004582
4583 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4584 goto out;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004585 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004586 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004587 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004588 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004589 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004590
William Lallemanddf1425a2015-04-28 20:17:49 +02004591 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4592 goto out;
4593
Willy Tarreau13943ab2006-12-31 00:24:10 +01004594 if (curproxy->cap & PR_CAP_FE)
4595 curproxy->options |= PR_O_TCP_CLI_KA;
4596 if (curproxy->cap & PR_CAP_BE)
4597 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004598 }
4599 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004600 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004601 err_code |= ERR_WARN;
4602
Willy Tarreaubaaee002006-06-26 02:48:02 +02004603 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004604 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004605 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004606 curproxy->options2 &= ~PR_O2_CHK_ANY;
4607 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004608 if (!*args[2]) { /* no argument */
4609 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4610 curproxy->check_len = strlen(DEF_CHECK_REQ);
4611 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004612 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004613 curproxy->check_req = (char *)malloc(reqlen);
4614 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004615 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004616 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004617 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004618 if (*args[4])
4619 reqlen += strlen(args[4]);
4620 else
4621 reqlen += strlen("HTTP/1.0");
4622
4623 curproxy->check_req = (char *)malloc(reqlen);
4624 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004625 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004626 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004627 if (alertif_too_many_args_idx(3, 1, file, linenum, args, &err_code))
4628 goto out;
Willy Tarreauf3c69202006-07-09 16:42:34 +02004629 }
4630 else if (!strcmp(args[1], "ssl-hello-chk")) {
4631 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004632 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004633 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004634
Willy Tarreaua534fea2008-08-03 12:19:50 +02004635 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004636 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004637 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004638 curproxy->options2 |= PR_O2_SSL3_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004639
4640 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4641 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004642 }
Willy Tarreau23677902007-05-08 23:50:35 +02004643 else if (!strcmp(args[1], "smtpchk")) {
4644 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004645 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004646 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004647 curproxy->options2 &= ~PR_O2_CHK_ANY;
4648 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004649
4650 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4651 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4652 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4653 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4654 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4655 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
4656 curproxy->check_req = (char *)malloc(reqlen);
4657 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4658 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4659 } else {
4660 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4661 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4662 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4663 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4664 }
4665 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004666 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4667 goto out;
Willy Tarreau23677902007-05-08 23:50:35 +02004668 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004669 else if (!strcmp(args[1], "pgsql-check")) {
4670 /* use PostgreSQL request to check servers' health */
4671 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4672 err_code |= ERR_WARN;
4673
4674 free(curproxy->check_req);
4675 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004676 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004677 curproxy->options2 |= PR_O2_PGSQL_CHK;
4678
4679 if (*(args[2])) {
4680 int cur_arg = 2;
4681
4682 while (*(args[cur_arg])) {
4683 if (strcmp(args[cur_arg], "user") == 0) {
4684 char * packet;
4685 uint32_t packet_len;
4686 uint32_t pv;
4687
4688 /* suboption header - needs additional argument for it */
4689 if (*(args[cur_arg+1]) == 0) {
4690 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4691 file, linenum, args[0], args[1], args[cur_arg]);
4692 err_code |= ERR_ALERT | ERR_FATAL;
4693 goto out;
4694 }
4695
4696 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4697 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4698 pv = htonl(0x30000); /* protocol version 3.0 */
4699
4700 packet = (char*) calloc(1, packet_len);
4701
4702 memcpy(packet + 4, &pv, 4);
4703
4704 /* copy "user" */
4705 memcpy(packet + 8, "user", 4);
4706
4707 /* copy username */
4708 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4709
4710 free(curproxy->check_req);
4711 curproxy->check_req = packet;
4712 curproxy->check_len = packet_len;
4713
4714 packet_len = htonl(packet_len);
4715 memcpy(packet, &packet_len, 4);
4716 cur_arg += 2;
4717 } else {
4718 /* unknown suboption - catchall */
4719 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4720 file, linenum, args[0], args[1]);
4721 err_code |= ERR_ALERT | ERR_FATAL;
4722 goto out;
4723 }
4724 } /* end while loop */
4725 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004726 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4727 goto out;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004728 }
4729
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004730 else if (!strcmp(args[1], "redis-check")) {
4731 /* use REDIS PING request to check servers' health */
4732 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4733 err_code |= ERR_WARN;
4734
4735 free(curproxy->check_req);
4736 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004737 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004738 curproxy->options2 |= PR_O2_REDIS_CHK;
4739
4740 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
4741 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4742 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004743
4744 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4745 goto out;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004746 }
4747
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004748 else if (!strcmp(args[1], "mysql-check")) {
4749 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004750 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4751 err_code |= ERR_WARN;
4752
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004753 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004754 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004755 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004756 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004757
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004758 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004759 * const char mysql40_client_auth_pkt[] = {
4760 * "\x0e\x00\x00" // packet length
4761 * "\x01" // packet number
4762 * "\x00\x00" // client capabilities
4763 * "\x00\x00\x01" // max packet
4764 * "haproxy\x00" // username (null terminated string)
4765 * "\x00" // filler (always 0x00)
4766 * "\x01\x00\x00" // packet length
4767 * "\x00" // packet number
4768 * "\x01" // COM_QUIT command
4769 * };
4770 */
4771
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004772 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4773 * const char mysql41_client_auth_pkt[] = {
4774 * "\x0e\x00\x00\" // packet length
4775 * "\x01" // packet number
4776 * "\x00\x00\x00\x00" // client capabilities
4777 * "\x00\x00\x00\x01" // max packet
4778 * "\x21" // character set (UTF-8)
4779 * char[23] // All zeroes
4780 * "haproxy\x00" // username (null terminated string)
4781 * "\x00" // filler (always 0x00)
4782 * "\x01\x00\x00" // packet length
4783 * "\x00" // packet number
4784 * "\x01" // COM_QUIT command
4785 * };
4786 */
4787
4788
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004789 if (*(args[2])) {
4790 int cur_arg = 2;
4791
4792 while (*(args[cur_arg])) {
4793 if (strcmp(args[cur_arg], "user") == 0) {
4794 char *mysqluser;
4795 int packetlen, reqlen, userlen;
4796
4797 /* suboption header - needs additional argument for it */
4798 if (*(args[cur_arg+1]) == 0) {
4799 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4800 file, linenum, args[0], args[1], args[cur_arg]);
4801 err_code |= ERR_ALERT | ERR_FATAL;
4802 goto out;
4803 }
4804 mysqluser = args[cur_arg + 1];
4805 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004806
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004807 if (*(args[cur_arg+2])) {
4808 if (!strcmp(args[cur_arg+2], "post-41")) {
4809 packetlen = userlen + 7 + 27;
4810 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004811
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004812 free(curproxy->check_req);
4813 curproxy->check_req = (char *)calloc(1, reqlen);
4814 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004815
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004816 snprintf(curproxy->check_req, 4, "%c%c%c",
4817 ((unsigned char) packetlen & 0xff),
4818 ((unsigned char) (packetlen >> 8) & 0xff),
4819 ((unsigned char) (packetlen >> 16) & 0xff));
4820
4821 curproxy->check_req[3] = 1;
4822 curproxy->check_req[5] = 130;
4823 curproxy->check_req[11] = 1;
4824 curproxy->check_req[12] = 33;
4825 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4826 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4827 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4828 cur_arg += 3;
4829 } else {
4830 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4831 err_code |= ERR_ALERT | ERR_FATAL;
4832 goto out;
4833 }
4834 } else {
4835 packetlen = userlen + 7;
4836 reqlen = packetlen + 9;
4837
4838 free(curproxy->check_req);
4839 curproxy->check_req = (char *)calloc(1, reqlen);
4840 curproxy->check_len = reqlen;
4841
4842 snprintf(curproxy->check_req, 4, "%c%c%c",
4843 ((unsigned char) packetlen & 0xff),
4844 ((unsigned char) (packetlen >> 8) & 0xff),
4845 ((unsigned char) (packetlen >> 16) & 0xff));
4846
4847 curproxy->check_req[3] = 1;
4848 curproxy->check_req[5] = 128;
4849 curproxy->check_req[8] = 1;
4850 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4851 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4852 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4853 cur_arg += 2;
4854 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004855 } else {
4856 /* unknown suboption - catchall */
4857 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4858 file, linenum, args[0], args[1]);
4859 err_code |= ERR_ALERT | ERR_FATAL;
4860 goto out;
4861 }
4862 } /* end while loop */
4863 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004864 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004865 else if (!strcmp(args[1], "ldap-check")) {
4866 /* use LDAP request to check servers' health */
4867 free(curproxy->check_req);
4868 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004869 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004870 curproxy->options2 |= PR_O2_LDAP_CHK;
4871
4872 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
4873 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
4874 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004875 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4876 goto out;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004877 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004878 else if (!strcmp(args[1], "tcp-check")) {
4879 /* use raw TCPCHK send/expect to check servers' health */
4880 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4881 err_code |= ERR_WARN;
4882
4883 free(curproxy->check_req);
4884 curproxy->check_req = NULL;
4885 curproxy->options2 &= ~PR_O2_CHK_ANY;
4886 curproxy->options2 |= PR_O2_TCPCHK_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004887 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4888 goto out;
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004889 }
Simon Horman98637e52014-06-20 12:30:16 +09004890 else if (!strcmp(args[1], "external-check")) {
4891 /* excute an external command to check servers' health */
4892 free(curproxy->check_req);
4893 curproxy->check_req = NULL;
4894 curproxy->options2 &= ~PR_O2_CHK_ANY;
4895 curproxy->options2 |= PR_O2_EXT_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004896 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4897 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09004898 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004899 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004900 int cur_arg;
4901
4902 /* insert x-forwarded-for field, but not for the IP address listed as an except.
4903 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004904 */
Ross Westaf72a1d2008-08-03 10:51:45 +02004905
Willy Tarreau87cf5142011-08-19 22:57:24 +02004906 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02004907
4908 free(curproxy->fwdfor_hdr_name);
4909 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
4910 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
4911
4912 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
4913 cur_arg = 2;
4914 while (*(args[cur_arg])) {
4915 if (!strcmp(args[cur_arg], "except")) {
4916 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004917 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004918 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4919 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004920 err_code |= ERR_ALERT | ERR_FATAL;
4921 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004922 }
4923 /* flush useless bits */
4924 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02004925 cur_arg += 2;
4926 } else if (!strcmp(args[cur_arg], "header")) {
4927 /* suboption header - needs additional argument for it */
4928 if (*(args[cur_arg+1]) == 0) {
4929 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4930 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004931 err_code |= ERR_ALERT | ERR_FATAL;
4932 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02004933 }
4934 free(curproxy->fwdfor_hdr_name);
4935 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
4936 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
4937 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02004938 } else if (!strcmp(args[cur_arg], "if-none")) {
4939 curproxy->options &= ~PR_O_FF_ALWAYS;
4940 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004941 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02004942 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02004943 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02004944 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004945 err_code |= ERR_ALERT | ERR_FATAL;
4946 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004947 }
Ross Westaf72a1d2008-08-03 10:51:45 +02004948 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004949 }
Maik Broemme2850cb42009-04-17 18:53:21 +02004950 else if (!strcmp(args[1], "originalto")) {
4951 int cur_arg;
4952
4953 /* insert x-original-to field, but not for the IP address listed as an except.
4954 * set default options (ie: bitfield, header name, etc)
4955 */
4956
4957 curproxy->options |= PR_O_ORGTO;
4958
4959 free(curproxy->orgto_hdr_name);
4960 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
4961 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
4962
Willy Tarreau87cf5142011-08-19 22:57:24 +02004963 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02004964 cur_arg = 2;
4965 while (*(args[cur_arg])) {
4966 if (!strcmp(args[cur_arg], "except")) {
4967 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004968 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 +02004969 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4970 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004971 err_code |= ERR_ALERT | ERR_FATAL;
4972 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004973 }
4974 /* flush useless bits */
4975 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
4976 cur_arg += 2;
4977 } else if (!strcmp(args[cur_arg], "header")) {
4978 /* suboption header - needs additional argument for it */
4979 if (*(args[cur_arg+1]) == 0) {
4980 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4981 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004982 err_code |= ERR_ALERT | ERR_FATAL;
4983 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004984 }
4985 free(curproxy->orgto_hdr_name);
4986 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
4987 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
4988 cur_arg += 2;
4989 } else {
4990 /* unknown suboption - catchall */
4991 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
4992 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004993 err_code |= ERR_ALERT | ERR_FATAL;
4994 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004995 }
4996 } /* end while loop */
4997 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004998 else {
4999 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005000 err_code |= ERR_ALERT | ERR_FATAL;
5001 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005002 }
Willy Tarreau93893792009-07-23 13:19:11 +02005003 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005004 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005005 else if (!strcmp(args[0], "default_backend")) {
5006 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005007 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005008
5009 if (*(args[1]) == 0) {
5010 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005011 err_code |= ERR_ALERT | ERR_FATAL;
5012 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005013 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005014 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005015 curproxy->defbe.name = strdup(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005016
5017 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5018 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005019 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005020 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01005021 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005022 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005023
Willy Tarreaua3c504c2014-04-28 22:37:32 +02005024 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
5025 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 +01005026 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005027 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005028 /* enable reconnections to dispatch */
5029 curproxy->options |= PR_O_REDISP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005030
5031 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5032 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005033 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005034 else if (!strcmp(args[0], "http-reuse")) {
5035 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5036 err_code |= ERR_WARN;
5037
5038 if (strcmp(args[1], "never") == 0) {
5039 /* enable a graceful server shutdown on an HTTP 404 response */
5040 curproxy->options &= ~PR_O_REUSE_MASK;
5041 curproxy->options |= PR_O_REUSE_NEVR;
5042 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5043 goto out;
5044 }
Willy Tarreau161d45f2015-08-05 16:02:46 +02005045 else if (strcmp(args[1], "safe") == 0) {
5046 /* enable a graceful server shutdown on an HTTP 404 response */
5047 curproxy->options &= ~PR_O_REUSE_MASK;
5048 curproxy->options |= PR_O_REUSE_SAFE;
5049 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5050 goto out;
5051 }
Willy Tarreau449d74a2015-08-05 17:16:33 +02005052 else if (strcmp(args[1], "aggressive") == 0) {
5053 curproxy->options &= ~PR_O_REUSE_MASK;
5054 curproxy->options |= PR_O_REUSE_AGGR;
5055 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5056 goto out;
5057 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005058 else if (strcmp(args[1], "always") == 0) {
5059 /* enable a graceful server shutdown on an HTTP 404 response */
5060 curproxy->options &= ~PR_O_REUSE_MASK;
5061 curproxy->options |= PR_O_REUSE_ALWS;
5062 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5063 goto out;
5064 }
5065 else {
Willy Tarreau449d74a2015-08-05 17:16:33 +02005066 Alert("parsing [%s:%d] : '%s' only supports 'never', 'safe', 'aggressive', 'always'.\n", file, linenum, args[0]);
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005067 err_code |= ERR_ALERT | ERR_FATAL;
5068 goto out;
5069 }
5070 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005071 else if (!strcmp(args[0], "http-check")) {
5072 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005073 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01005074
5075 if (strcmp(args[1], "disable-on-404") == 0) {
5076 /* enable a graceful server shutdown on an HTTP 404 response */
5077 curproxy->options |= PR_O_DISABLE404;
William Lallemanddf1425a2015-04-28 20:17:49 +02005078 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5079 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005080 }
Willy Tarreauef781042010-01-27 11:53:01 +01005081 else if (strcmp(args[1], "send-state") == 0) {
5082 /* enable emission of the apparent state of a server in HTTP checks */
5083 curproxy->options2 |= PR_O2_CHK_SNDST;
William Lallemanddf1425a2015-04-28 20:17:49 +02005084 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5085 goto out;
Willy Tarreauef781042010-01-27 11:53:01 +01005086 }
Willy Tarreaubd741542010-03-16 18:46:54 +01005087 else if (strcmp(args[1], "expect") == 0) {
5088 const char *ptr_arg;
5089 int cur_arg;
5090
5091 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5092 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5093 err_code |= ERR_ALERT | ERR_FATAL;
5094 goto out;
5095 }
5096
5097 cur_arg = 2;
5098 /* consider exclamation marks, sole or at the beginning of a word */
5099 while (*(ptr_arg = args[cur_arg])) {
5100 while (*ptr_arg == '!') {
5101 curproxy->options2 ^= PR_O2_EXP_INV;
5102 ptr_arg++;
5103 }
5104 if (*ptr_arg)
5105 break;
5106 cur_arg++;
5107 }
5108 /* now ptr_arg points to the beginning of a word past any possible
5109 * exclamation mark, and cur_arg is the argument which holds this word.
5110 */
5111 if (strcmp(ptr_arg, "status") == 0) {
5112 if (!*(args[cur_arg + 1])) {
5113 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5114 file, linenum, args[0], args[1], ptr_arg);
5115 err_code |= ERR_ALERT | ERR_FATAL;
5116 goto out;
5117 }
5118 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005119 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005120 curproxy->expect_str = strdup(args[cur_arg + 1]);
5121 }
5122 else if (strcmp(ptr_arg, "string") == 0) {
5123 if (!*(args[cur_arg + 1])) {
5124 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5125 file, linenum, args[0], args[1], ptr_arg);
5126 err_code |= ERR_ALERT | ERR_FATAL;
5127 goto out;
5128 }
5129 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005130 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005131 curproxy->expect_str = strdup(args[cur_arg + 1]);
5132 }
5133 else if (strcmp(ptr_arg, "rstatus") == 0) {
5134 if (!*(args[cur_arg + 1])) {
5135 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5136 file, linenum, args[0], args[1], ptr_arg);
5137 err_code |= ERR_ALERT | ERR_FATAL;
5138 goto out;
5139 }
5140 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005141 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005142 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005143 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005144 free(curproxy->expect_regex);
5145 curproxy->expect_regex = NULL;
5146 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005147 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005148 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5149 error = NULL;
5150 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5151 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5152 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5153 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005154 err_code |= ERR_ALERT | ERR_FATAL;
5155 goto out;
5156 }
5157 }
5158 else if (strcmp(ptr_arg, "rstring") == 0) {
5159 if (!*(args[cur_arg + 1])) {
5160 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5161 file, linenum, args[0], args[1], ptr_arg);
5162 err_code |= ERR_ALERT | ERR_FATAL;
5163 goto out;
5164 }
5165 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005166 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005167 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005168 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005169 free(curproxy->expect_regex);
5170 curproxy->expect_regex = NULL;
5171 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005172 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005173 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5174 error = NULL;
5175 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5176 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5177 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5178 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005179 err_code |= ERR_ALERT | ERR_FATAL;
5180 goto out;
5181 }
5182 }
5183 else {
5184 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
5185 file, linenum, args[0], args[1], ptr_arg);
5186 err_code |= ERR_ALERT | ERR_FATAL;
5187 goto out;
5188 }
5189 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005190 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005191 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 +02005192 err_code |= ERR_ALERT | ERR_FATAL;
5193 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005194 }
5195 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005196 else if (!strcmp(args[0], "tcp-check")) {
5197 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5198 err_code |= ERR_WARN;
5199
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005200 if (strcmp(args[1], "comment") == 0) {
5201 int cur_arg;
5202 struct tcpcheck_rule *tcpcheck;
5203
5204 cur_arg = 1;
5205 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5206 tcpcheck->action = TCPCHK_ACT_COMMENT;
5207
5208 if (!*args[cur_arg + 1]) {
5209 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5210 file, linenum, args[cur_arg]);
5211 err_code |= ERR_ALERT | ERR_FATAL;
5212 goto out;
5213 }
5214
5215 tcpcheck->comment = strdup(args[cur_arg + 1]);
5216
5217 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
William Lallemanddf1425a2015-04-28 20:17:49 +02005218 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
5219 goto out;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005220 }
5221 else if (strcmp(args[1], "connect") == 0) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005222 const char *ptr_arg;
5223 int cur_arg;
5224 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005225
5226 /* check if first rule is also a 'connect' action */
Willy Tarreau5581c272015-05-13 12:24:53 +02005227 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
5228 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
5229 tcpcheck->action == TCPCHK_ACT_COMMENT) {
5230 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
5231 }
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005232
Willy Tarreau5581c272015-05-13 12:24:53 +02005233 if (&tcpcheck->list != &curproxy->tcpcheck_rules
5234 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
5235 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
5236 file, linenum);
5237 err_code |= ERR_ALERT | ERR_FATAL;
5238 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005239 }
5240
5241 cur_arg = 2;
5242 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5243 tcpcheck->action = TCPCHK_ACT_CONNECT;
5244
5245 /* parsing each parameters to fill up the rule */
5246 while (*(ptr_arg = args[cur_arg])) {
5247 /* tcp port */
5248 if (strcmp(args[cur_arg], "port") == 0) {
5249 if ( (atol(args[cur_arg + 1]) > 65535) ||
5250 (atol(args[cur_arg + 1]) < 1) ){
5251 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
5252 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
5253 err_code |= ERR_ALERT | ERR_FATAL;
5254 goto out;
5255 }
5256 tcpcheck->port = atol(args[cur_arg + 1]);
5257 cur_arg += 2;
5258 }
5259 /* send proxy protocol */
5260 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
5261 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
5262 cur_arg++;
5263 }
5264#ifdef USE_OPENSSL
5265 else if (strcmp(args[cur_arg], "ssl") == 0) {
5266 curproxy->options |= PR_O_TCPCHK_SSL;
5267 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
5268 cur_arg++;
5269 }
5270#endif /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005271 /* comment for this tcpcheck line */
5272 else if (strcmp(args[cur_arg], "comment") == 0) {
5273 if (!*args[cur_arg + 1]) {
5274 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5275 file, linenum, args[cur_arg]);
5276 err_code |= ERR_ALERT | ERR_FATAL;
5277 goto out;
5278 }
5279 tcpcheck->comment = strdup(args[cur_arg + 1]);
5280 cur_arg += 2;
5281 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005282 else {
5283#ifdef USE_OPENSSL
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005284 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 +01005285#else /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005286 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 +01005287#endif /* USE_OPENSSL */
5288 file, linenum, args[0], args[1], args[cur_arg]);
5289 err_code |= ERR_ALERT | ERR_FATAL;
5290 goto out;
5291 }
5292
5293 }
5294
5295 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5296 }
5297 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005298 if (! *(args[2]) ) {
5299 /* SEND string expected */
5300 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
5301 file, linenum, args[0], args[1], args[2]);
5302 err_code |= ERR_ALERT | ERR_FATAL;
5303 goto out;
5304 } else {
5305 struct tcpcheck_rule *tcpcheck;
5306
5307 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5308
5309 tcpcheck->action = TCPCHK_ACT_SEND;
5310 tcpcheck->string_len = strlen(args[2]);
5311 tcpcheck->string = strdup(args[2]);
5312 tcpcheck->expect_regex = NULL;
5313
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005314 /* comment for this tcpcheck line */
5315 if (strcmp(args[3], "comment") == 0) {
5316 if (!*args[4]) {
5317 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5318 file, linenum, args[3]);
5319 err_code |= ERR_ALERT | ERR_FATAL;
5320 goto out;
5321 }
5322 tcpcheck->comment = strdup(args[4]);
5323 }
5324
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005325 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5326 }
5327 }
5328 else if (strcmp(args[1], "send-binary") == 0) {
5329 if (! *(args[2]) ) {
5330 /* SEND binary string expected */
5331 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
5332 file, linenum, args[0], args[1], args[2]);
5333 err_code |= ERR_ALERT | ERR_FATAL;
5334 goto out;
5335 } else {
5336 struct tcpcheck_rule *tcpcheck;
5337 char *err = NULL;
5338
5339 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5340
5341 tcpcheck->action = TCPCHK_ACT_SEND;
5342 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5343 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5344 file, linenum, args[0], args[1], args[2], err);
5345 err_code |= ERR_ALERT | ERR_FATAL;
5346 goto out;
5347 }
5348 tcpcheck->expect_regex = NULL;
5349
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005350 /* comment for this tcpcheck line */
5351 if (strcmp(args[3], "comment") == 0) {
5352 if (!*args[4]) {
5353 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5354 file, linenum, args[3]);
5355 err_code |= ERR_ALERT | ERR_FATAL;
5356 goto out;
5357 }
5358 tcpcheck->comment = strdup(args[4]);
5359 }
5360
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005361 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5362 }
5363 }
5364 else if (strcmp(args[1], "expect") == 0) {
5365 const char *ptr_arg;
5366 int cur_arg;
5367 int inverse = 0;
5368
5369 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5370 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5371 err_code |= ERR_ALERT | ERR_FATAL;
5372 goto out;
5373 }
5374
5375 cur_arg = 2;
5376 /* consider exclamation marks, sole or at the beginning of a word */
5377 while (*(ptr_arg = args[cur_arg])) {
5378 while (*ptr_arg == '!') {
5379 inverse = !inverse;
5380 ptr_arg++;
5381 }
5382 if (*ptr_arg)
5383 break;
5384 cur_arg++;
5385 }
5386 /* now ptr_arg points to the beginning of a word past any possible
5387 * exclamation mark, and cur_arg is the argument which holds this word.
5388 */
5389 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005390 struct tcpcheck_rule *tcpcheck;
5391 char *err = NULL;
5392
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005393 if (!*(args[cur_arg + 1])) {
5394 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
5395 file, linenum, args[0], args[1], ptr_arg);
5396 err_code |= ERR_ALERT | ERR_FATAL;
5397 goto out;
5398 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005399
5400 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5401
5402 tcpcheck->action = TCPCHK_ACT_EXPECT;
5403 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5404 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5405 file, linenum, args[0], args[1], args[2], err);
5406 err_code |= ERR_ALERT | ERR_FATAL;
5407 goto out;
5408 }
5409 tcpcheck->expect_regex = NULL;
5410 tcpcheck->inverse = inverse;
5411
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005412 /* tcpcheck comment */
5413 cur_arg += 2;
5414 if (strcmp(args[cur_arg], "comment") == 0) {
5415 if (!*args[cur_arg + 1]) {
5416 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5417 file, linenum, args[cur_arg + 1]);
5418 err_code |= ERR_ALERT | ERR_FATAL;
5419 goto out;
5420 }
5421 tcpcheck->comment = strdup(args[cur_arg + 1]);
5422 }
5423
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005424 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5425 }
5426 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005427 struct tcpcheck_rule *tcpcheck;
5428
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005429 if (!*(args[cur_arg + 1])) {
5430 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5431 file, linenum, args[0], args[1], ptr_arg);
5432 err_code |= ERR_ALERT | ERR_FATAL;
5433 goto out;
5434 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005435
5436 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5437
5438 tcpcheck->action = TCPCHK_ACT_EXPECT;
5439 tcpcheck->string_len = strlen(args[cur_arg + 1]);
5440 tcpcheck->string = strdup(args[cur_arg + 1]);
5441 tcpcheck->expect_regex = NULL;
5442 tcpcheck->inverse = inverse;
5443
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005444 /* tcpcheck comment */
5445 cur_arg += 2;
5446 if (strcmp(args[cur_arg], "comment") == 0) {
5447 if (!*args[cur_arg + 1]) {
5448 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5449 file, linenum, args[cur_arg + 1]);
5450 err_code |= ERR_ALERT | ERR_FATAL;
5451 goto out;
5452 }
5453 tcpcheck->comment = strdup(args[cur_arg + 1]);
5454 }
5455
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005456 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5457 }
5458 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005459 struct tcpcheck_rule *tcpcheck;
5460
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005461 if (!*(args[cur_arg + 1])) {
5462 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5463 file, linenum, args[0], args[1], ptr_arg);
5464 err_code |= ERR_ALERT | ERR_FATAL;
5465 goto out;
5466 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005467
5468 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5469
5470 tcpcheck->action = TCPCHK_ACT_EXPECT;
5471 tcpcheck->string_len = 0;
5472 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005473 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
5474 error = NULL;
5475 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
5476 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5477 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5478 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005479 err_code |= ERR_ALERT | ERR_FATAL;
5480 goto out;
5481 }
5482 tcpcheck->inverse = inverse;
5483
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005484 /* tcpcheck comment */
5485 cur_arg += 2;
5486 if (strcmp(args[cur_arg], "comment") == 0) {
5487 if (!*args[cur_arg + 1]) {
5488 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5489 file, linenum, args[cur_arg + 1]);
5490 err_code |= ERR_ALERT | ERR_FATAL;
5491 goto out;
5492 }
5493 tcpcheck->comment = strdup(args[cur_arg + 1]);
5494 }
5495
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005496 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5497 }
5498 else {
5499 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
5500 file, linenum, args[0], args[1], ptr_arg);
5501 err_code |= ERR_ALERT | ERR_FATAL;
5502 goto out;
5503 }
5504 }
5505 else {
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005506 Alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005507 err_code |= ERR_ALERT | ERR_FATAL;
5508 goto out;
5509 }
5510 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01005511 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02005512 if (curproxy == &defproxy) {
5513 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005514 err_code |= ERR_ALERT | ERR_FATAL;
5515 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02005516 }
5517
Willy Tarreaub80c2302007-11-30 20:51:32 +01005518 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005519 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005520
5521 if (strcmp(args[1], "fail") == 0) {
5522 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01005523 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01005524 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
5525 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005526 err_code |= ERR_ALERT | ERR_FATAL;
5527 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005528 }
5529
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005530 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
5531 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
5532 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005533 err_code |= ERR_ALERT | ERR_FATAL;
5534 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005535 }
5536 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
5537 }
5538 else {
5539 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005540 err_code |= ERR_ALERT | ERR_FATAL;
5541 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005542 }
5543 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005544#ifdef TPROXY
5545 else if (!strcmp(args[0], "transparent")) {
5546 /* enable transparent proxy connections */
5547 curproxy->options |= PR_O_TRANSP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005548 if (alertif_too_many_args(0, file, linenum, args, &err_code))
5549 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005550 }
5551#endif
5552 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005553 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005554 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005555
Willy Tarreaubaaee002006-06-26 02:48:02 +02005556 if (*(args[1]) == 0) {
5557 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005558 err_code |= ERR_ALERT | ERR_FATAL;
5559 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005560 }
5561 curproxy->maxconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005562 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5563 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005564 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005565 else if (!strcmp(args[0], "backlog")) { /* backlog */
5566 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005567 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005568
5569 if (*(args[1]) == 0) {
5570 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005571 err_code |= ERR_ALERT | ERR_FATAL;
5572 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005573 }
5574 curproxy->backlog = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005575 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5576 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005577 }
Willy Tarreau86034312006-12-29 00:10:33 +01005578 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005579 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005580 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005581
Willy Tarreau86034312006-12-29 00:10:33 +01005582 if (*(args[1]) == 0) {
5583 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005584 err_code |= ERR_ALERT | ERR_FATAL;
5585 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005586 }
5587 curproxy->fullconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005588 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5589 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005590 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005591 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
5592 if (*(args[1]) == 0) {
5593 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005594 err_code |= ERR_ALERT | ERR_FATAL;
5595 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005596 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005597 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
5598 if (err) {
5599 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
5600 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02005601 err_code |= ERR_ALERT | ERR_FATAL;
5602 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005603 }
5604 curproxy->grace = val;
William Lallemanddf1425a2015-04-28 20:17:49 +02005605 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5606 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005607 }
5608 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01005609 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005610 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005611 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005612
Willy Tarreaubaaee002006-06-26 02:48:02 +02005613 if (curproxy == &defproxy) {
5614 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005615 err_code |= ERR_ALERT | ERR_FATAL;
5616 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005617 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005618 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005619 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005620
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02005621 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005622 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005623 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005624 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005625 goto out;
5626 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005627
5628 proto = protocol_by_family(sk->ss_family);
5629 if (!proto || !proto->connect) {
5630 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5631 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005632 err_code |= ERR_ALERT | ERR_FATAL;
5633 goto out;
5634 }
5635
5636 if (port1 != port2) {
5637 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5638 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005639 err_code |= ERR_ALERT | ERR_FATAL;
5640 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005641 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005642
5643 if (!port1) {
5644 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5645 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005646 err_code |= ERR_ALERT | ERR_FATAL;
5647 goto out;
5648 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005649
William Lallemanddf1425a2015-04-28 20:17:49 +02005650 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5651 goto out;
5652
Willy Tarreaud5191e72010-02-09 20:50:45 +01005653 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005654 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005655 }
5656 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005657 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005658 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005659
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005660 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5661 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005662 err_code |= ERR_ALERT | ERR_FATAL;
5663 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005664 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005665 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005666 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005667 /**
5668 * The syntax for hash-type config element is
5669 * hash-type {map-based|consistent} [[<algo>] avalanche]
5670 *
5671 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5672 */
5673 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005674
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005675 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5676 err_code |= ERR_WARN;
5677
5678 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005679 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5680 }
5681 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005682 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5683 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005684 else if (strcmp(args[1], "avalanche") == 0) {
5685 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]);
5686 err_code |= ERR_ALERT | ERR_FATAL;
5687 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005688 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005689 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005690 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005691 err_code |= ERR_ALERT | ERR_FATAL;
5692 goto out;
5693 }
Bhaskar98634f02013-10-29 23:30:51 -04005694
5695 /* set the hash function to use */
5696 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005697 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005698 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005699
5700 /* if consistent with no argument, then avalanche modifier is also applied */
5701 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5702 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005703 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005704 /* set the hash function */
5705 if (!strcmp(args[2], "sdbm")) {
5706 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5707 }
5708 else if (!strcmp(args[2], "djb2")) {
5709 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005710 }
5711 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005712 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005713 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005714 else if (!strcmp(args[2], "crc32")) {
5715 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5716 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005717 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005718 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 -05005719 err_code |= ERR_ALERT | ERR_FATAL;
5720 goto out;
5721 }
5722
5723 /* set the hash modifier */
5724 if (!strcmp(args[3], "avalanche")) {
5725 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5726 }
5727 else if (*args[3]) {
5728 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5729 err_code |= ERR_ALERT | ERR_FATAL;
5730 goto out;
5731 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005732 }
William Lallemanda73203e2012-03-12 12:48:57 +01005733 }
William Lallemanda73203e2012-03-12 12:48:57 +01005734 else if (strcmp(args[0], "unique-id-format") == 0) {
5735 if (!*(args[1])) {
5736 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5737 err_code |= ERR_ALERT | ERR_FATAL;
5738 goto out;
5739 }
William Lallemand3203ff42012-11-11 17:30:56 +01005740 if (*(args[2])) {
5741 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5742 err_code |= ERR_ALERT | ERR_FATAL;
5743 goto out;
5744 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005745 free(curproxy->conf.uniqueid_format_string);
5746 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005747
Willy Tarreau62a61232013-04-12 18:13:46 +02005748 free(curproxy->conf.uif_file);
5749 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5750 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005751 }
William Lallemanda73203e2012-03-12 12:48:57 +01005752
5753 else if (strcmp(args[0], "unique-id-header") == 0) {
5754 if (!*(args[1])) {
5755 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5756 err_code |= ERR_ALERT | ERR_FATAL;
5757 goto out;
5758 }
5759 free(curproxy->header_unique_id);
5760 curproxy->header_unique_id = strdup(args[1]);
5761 }
5762
William Lallemand723b73a2012-02-08 16:37:49 +01005763 else if (strcmp(args[0], "log-format") == 0) {
5764 if (!*(args[1])) {
5765 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5766 err_code |= ERR_ALERT | ERR_FATAL;
5767 goto out;
5768 }
William Lallemand3203ff42012-11-11 17:30:56 +01005769 if (*(args[2])) {
5770 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5771 err_code |= ERR_ALERT | ERR_FATAL;
5772 goto out;
5773 }
Willy Tarreau196729e2012-05-31 19:30:26 +02005774
Willy Tarreau62a61232013-04-12 18:13:46 +02005775 if (curproxy->conf.logformat_string != default_http_log_format &&
5776 curproxy->conf.logformat_string != default_tcp_log_format &&
5777 curproxy->conf.logformat_string != clf_http_log_format)
5778 free(curproxy->conf.logformat_string);
5779 curproxy->conf.logformat_string = strdup(args[1]);
5780
5781 free(curproxy->conf.lfs_file);
5782 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5783 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005784
5785 /* get a chance to improve log-format error reporting by
5786 * reporting the correct line-number when possible.
5787 */
5788 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5789 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5790 file, linenum, curproxy->id);
5791 err_code |= ERR_WARN;
5792 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005793 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01005794 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
5795 if (*(args[1]) == 0) {
5796 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
5797 err_code |= ERR_ALERT | ERR_FATAL;
5798 goto out;
5799 }
5800 free(curproxy->log_tag);
5801 curproxy->log_tag = strdup(args[1]);
5802 }
William Lallemand0f99e342011-10-12 17:50:54 +02005803 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
5804 /* delete previous herited or defined syslog servers */
5805 struct logsrv *back;
5806
5807 if (*(args[1]) != 0) {
5808 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
5809 err_code |= ERR_ALERT | ERR_FATAL;
5810 goto out;
5811 }
5812
William Lallemand723b73a2012-02-08 16:37:49 +01005813 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
5814 LIST_DEL(&tmplogsrv->list);
5815 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02005816 }
5817 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005818 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02005819 struct logsrv *logsrv;
5820
Willy Tarreaubaaee002006-06-26 02:48:02 +02005821 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005822 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01005823 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02005824 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01005825 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02005826 LIST_INIT(&node->list);
5827 LIST_ADDQ(&curproxy->logsrvs, &node->list);
5828 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005829 }
5830 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005831 struct sockaddr_storage *sk;
5832 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02005833 int arg = 0;
5834 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02005835
5836 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005837
Willy Tarreau18324f52014-06-27 18:10:07 +02005838 /* just after the address, a length may be specified */
5839 if (strcmp(args[arg+2], "len") == 0) {
5840 len = atoi(args[arg+3]);
5841 if (len < 80 || len > 65535) {
5842 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
5843 file, linenum, args[arg+3]);
5844 err_code |= ERR_ALERT | ERR_FATAL;
5845 goto out;
5846 }
5847 logsrv->maxlen = len;
5848
5849 /* skip these two args */
5850 arg += 2;
5851 }
5852 else
5853 logsrv->maxlen = MAX_SYSLOG_LEN;
5854
5855 if (logsrv->maxlen > global.max_syslog_len) {
5856 global.max_syslog_len = logsrv->maxlen;
Dragan Dosen59cee972015-09-19 22:09:02 +02005857 logheader = realloc(logheader, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02005858 logline = realloc(logline, global.max_syslog_len + 1);
5859 }
5860
William Lallemanddf1425a2015-04-28 20:17:49 +02005861 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
5862 goto out;
5863
Willy Tarreau18324f52014-06-27 18:10:07 +02005864 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005865 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005866 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005867 err_code |= ERR_ALERT | ERR_FATAL;
5868 goto out;
5869
Willy Tarreaubaaee002006-06-26 02:48:02 +02005870 }
5871
William Lallemand0f99e342011-10-12 17:50:54 +02005872 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02005873 if (*(args[arg+3])) {
5874 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005875 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005876 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005877 err_code |= ERR_ALERT | ERR_FATAL;
5878 goto out;
5879
Willy Tarreaubaaee002006-06-26 02:48:02 +02005880 }
5881 }
5882
William Lallemand0f99e342011-10-12 17:50:54 +02005883 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02005884 if (*(args[arg+4])) {
5885 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01005886 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005887 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02005888 err_code |= ERR_ALERT | ERR_FATAL;
5889 goto out;
5890
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005891 }
5892 }
5893
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02005894 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005895 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005896 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005897 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005898 goto out;
5899 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005900
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005901 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005902
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005903 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005904 if (port1 != port2) {
5905 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5906 file, linenum, args[0], args[1]);
5907 err_code |= ERR_ALERT | ERR_FATAL;
5908 goto out;
5909 }
5910
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005911 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02005912 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005913 }
William Lallemand0f99e342011-10-12 17:50:54 +02005914
5915 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005916 }
5917 else {
5918 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
5919 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005920 err_code |= ERR_ALERT | ERR_FATAL;
5921 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005922 }
5923 }
5924 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005925 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005926 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01005927 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005928 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005929
Willy Tarreau977b8e42006-12-29 14:19:17 +01005930 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005931 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005932
Willy Tarreaubaaee002006-06-26 02:48:02 +02005933 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005934 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
5935 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005936 err_code |= ERR_ALERT | ERR_FATAL;
5937 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005938 }
Willy Tarreau368480c2009-03-01 08:27:21 +01005939
5940 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01005941 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5942 free(curproxy->conn_src.iface_name);
5943 curproxy->conn_src.iface_name = NULL;
5944 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01005945
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02005946 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005947 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005948 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005949 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005950 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005951 goto out;
5952 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005953
5954 proto = protocol_by_family(sk->ss_family);
5955 if (!proto || !proto->connect) {
5956 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005957 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005958 err_code |= ERR_ALERT | ERR_FATAL;
5959 goto out;
5960 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005961
5962 if (port1 != port2) {
5963 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5964 file, linenum, args[0], args[1]);
5965 err_code |= ERR_ALERT | ERR_FATAL;
5966 goto out;
5967 }
5968
Willy Tarreauef9a3602012-12-08 22:29:20 +01005969 curproxy->conn_src.source_addr = *sk;
5970 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005971
5972 cur_arg = 2;
5973 while (*(args[cur_arg])) {
5974 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau29fbe512015-08-20 19:35:14 +02005975#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005976 if (!*args[cur_arg + 1]) {
5977 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5978 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005979 err_code |= ERR_ALERT | ERR_FATAL;
5980 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005981 }
5982
5983 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005984 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5985 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005986 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005987 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5988 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005989 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5990 char *name, *end;
5991
5992 name = args[cur_arg+1] + 7;
5993 while (isspace(*name))
5994 name++;
5995
5996 end = name;
5997 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5998 end++;
5999
Willy Tarreauef9a3602012-12-08 22:29:20 +01006000 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6001 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
6002 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
6003 curproxy->conn_src.bind_hdr_len = end - name;
6004 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
6005 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
6006 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02006007
6008 /* now look for an occurrence number */
6009 while (isspace(*end))
6010 end++;
6011 if (*end == ',') {
6012 end++;
6013 name = end;
6014 if (*end == '-')
6015 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01006016 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02006017 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01006018 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006019 }
6020
Willy Tarreauef9a3602012-12-08 22:29:20 +01006021 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02006022 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
6023 " occurrences values smaller than %d.\n",
6024 file, linenum, MAX_HDR_HISTORY);
6025 err_code |= ERR_ALERT | ERR_FATAL;
6026 goto out;
6027 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006028 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01006029 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006030
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006031 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006032 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006033 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006034 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006035 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006036 goto out;
6037 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006038
6039 proto = protocol_by_family(sk->ss_family);
6040 if (!proto || !proto->connect) {
6041 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
6042 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006043 err_code |= ERR_ALERT | ERR_FATAL;
6044 goto out;
6045 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006046
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006047 if (port1 != port2) {
6048 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6049 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006050 err_code |= ERR_ALERT | ERR_FATAL;
6051 goto out;
6052 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006053 curproxy->conn_src.tproxy_addr = *sk;
6054 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006055 }
6056 global.last_checks |= LSTCHK_NETADM;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006057#else /* no TPROXY support */
6058 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01006059 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006060 err_code |= ERR_ALERT | ERR_FATAL;
6061 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006062#endif
6063 cur_arg += 2;
6064 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01006065 }
6066
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006067 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
6068#ifdef SO_BINDTODEVICE
6069 if (!*args[cur_arg + 1]) {
6070 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
6071 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006072 err_code |= ERR_ALERT | ERR_FATAL;
6073 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006074 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006075 free(curproxy->conn_src.iface_name);
6076 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
6077 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006078 global.last_checks |= LSTCHK_NETADM;
6079#else
6080 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
6081 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02006082 err_code |= ERR_ALERT | ERR_FATAL;
6083 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01006084#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006085 cur_arg += 2;
6086 continue;
6087 }
6088 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02006089 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006090 err_code |= ERR_ALERT | ERR_FATAL;
6091 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006092 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006093 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006094 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
6095 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
6096 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02006097 err_code |= ERR_ALERT | ERR_FATAL;
6098 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006099 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006100 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006101 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006102 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6103 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006104 err_code |= ERR_ALERT | ERR_FATAL;
6105 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006106 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006107
6108 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006109 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006110 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006111 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006112 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006113 }
6114 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006115 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006116 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006117 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006118 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006119 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006120 }
6121 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006122 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006123 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006124 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006125 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006126 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006127 }
6128 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006129 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006130 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006131 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006132 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006133 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006134 }
6135 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006136 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006137 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006138 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006139 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006140 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006141 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006142 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006143 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006144 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006145 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006146 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006147 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006148 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006149 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006150 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006151 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6152 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006153 err_code |= ERR_ALERT | ERR_FATAL;
6154 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006155 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006156
6157 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006158 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006159 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006160 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006161 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006162 }
6163 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006164 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006165 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006166 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006167 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006168 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006169 }
6170 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006171 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006172 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006173 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006174 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006175 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006176 }
6177 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006178 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006179 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006180 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006181 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006182 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006183 }
6184 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006185 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006186 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006187 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006188 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006189 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006190 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006191 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006192 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006193 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006194 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006195 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006196 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006197 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006198 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006199 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006200
Willy Tarreaubaaee002006-06-26 02:48:02 +02006201 if (curproxy == &defproxy) {
6202 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006203 err_code |= ERR_ALERT | ERR_FATAL;
6204 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006205 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006206 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006207 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006208
Willy Tarreaubaaee002006-06-26 02:48:02 +02006209 if (*(args[1]) == 0) {
6210 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006211 err_code |= ERR_ALERT | ERR_FATAL;
6212 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006213 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006214
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006215 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006216 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6217 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6218 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006219 err_code |= ERR_ALERT | ERR_FATAL;
6220 goto out;
6221 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006222 err_code |= warnif_cond_conflicts(cond,
6223 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6224 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006225 }
6226 else if (*args[2]) {
6227 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6228 file, linenum, args[0], args[2]);
6229 err_code |= ERR_ALERT | ERR_FATAL;
6230 goto out;
6231 }
6232
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006233 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006234 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006235 wl->s = strdup(args[1]);
6236 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02006237 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006238 }
6239 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006240 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006241 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6242 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006243 err_code |= ERR_ALERT | ERR_FATAL;
6244 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006245 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006246
Willy Tarreauade5ec42010-01-28 19:33:49 +01006247 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006248 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006249 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006250 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006251 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006252 }
6253 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006254 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006255 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006256 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006257 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006258 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006259 }
6260 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006261 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006262 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006263 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006264 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006265 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006266 }
6267 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006268 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006269 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6270 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006271 err_code |= ERR_ALERT | ERR_FATAL;
6272 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006273 }
6274
Willy Tarreauade5ec42010-01-28 19:33:49 +01006275 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006276 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006277 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006278 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006279 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006280 }
6281 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006282 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006283 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006284 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006285 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006286 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006287 }
6288 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006289 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006290 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006291 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006292 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006293 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006294 }
6295 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006296 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006297
Willy Tarreaubaaee002006-06-26 02:48:02 +02006298 if (curproxy == &defproxy) {
6299 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006300 err_code |= ERR_ALERT | ERR_FATAL;
6301 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006302 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006303 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006304 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006305
Willy Tarreaubaaee002006-06-26 02:48:02 +02006306 if (*(args[1]) == 0) {
6307 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006308 err_code |= ERR_ALERT | ERR_FATAL;
6309 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006310 }
6311
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006312 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006313 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6314 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6315 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006316 err_code |= ERR_ALERT | ERR_FATAL;
6317 goto out;
6318 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006319 err_code |= warnif_cond_conflicts(cond,
6320 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
6321 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006322 }
6323 else if (*args[2]) {
6324 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6325 file, linenum, args[0], args[2]);
6326 err_code |= ERR_ALERT | ERR_FATAL;
6327 goto out;
6328 }
6329
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006330 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006331 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006332 wl->s = strdup(args[1]);
6333 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006334 }
6335 else if (!strcmp(args[0], "errorloc") ||
6336 !strcmp(args[0], "errorloc302") ||
6337 !strcmp(args[0], "errorloc303")) { /* error location */
6338 int errnum, errlen;
6339 char *err;
6340
Willy Tarreau977b8e42006-12-29 14:19:17 +01006341 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006342 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006343
Willy Tarreaubaaee002006-06-26 02:48:02 +02006344 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006345 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006346 err_code |= ERR_ALERT | ERR_FATAL;
6347 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006348 }
6349
6350 errnum = atol(args[1]);
6351 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006352 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
6353 err = malloc(errlen);
6354 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006355 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006356 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
6357 err = malloc(errlen);
6358 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006359 }
6360
Willy Tarreau0f772532006-12-23 20:51:41 +01006361 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6362 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006363 chunk_destroy(&curproxy->errmsg[rc]);
6364 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01006365 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006366 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006367 }
Willy Tarreau0f772532006-12-23 20:51:41 +01006368
6369 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006370 Warning("parsing [%s:%d] : status code %d not handled by '%s', error relocation will be ignored.\n",
6371 file, linenum, errnum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006372 free(err);
6373 }
6374 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02006375 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
6376 int errnum, errlen, fd;
6377 char *err;
6378 struct stat stat;
6379
6380 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006381 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006382
6383 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006384 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006385 err_code |= ERR_ALERT | ERR_FATAL;
6386 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006387 }
6388
6389 fd = open(args[2], O_RDONLY);
6390 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
6391 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
6392 file, linenum, args[2], args[1]);
6393 if (fd >= 0)
6394 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02006395 err_code |= ERR_ALERT | ERR_FATAL;
6396 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006397 }
6398
Willy Tarreau27a674e2009-08-17 07:23:33 +02006399 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02006400 errlen = stat.st_size;
6401 } else {
6402 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02006403 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02006404 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02006405 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006406 }
6407
6408 err = malloc(errlen); /* malloc() must succeed during parsing */
6409 errnum = read(fd, err, errlen);
6410 if (errnum != errlen) {
6411 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
6412 file, linenum, args[2], args[1]);
6413 close(fd);
6414 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02006415 err_code |= ERR_ALERT | ERR_FATAL;
6416 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006417 }
6418 close(fd);
6419
6420 errnum = atol(args[1]);
6421 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6422 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006423 chunk_destroy(&curproxy->errmsg[rc]);
6424 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02006425 break;
6426 }
6427 }
6428
6429 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006430 Warning("parsing [%s:%d] : status code %d not handled by '%s', error customization will be ignored.\n",
6431 file, linenum, errnum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006432 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006433 free(err);
6434 }
6435 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006436 else if (!strcmp(args[0], "compression")) {
6437 struct comp *comp;
6438 if (curproxy->comp == NULL) {
6439 comp = calloc(1, sizeof(struct comp));
6440 curproxy->comp = comp;
6441 } else {
6442 comp = curproxy->comp;
6443 }
6444
6445 if (!strcmp(args[1], "algo")) {
6446 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01006447 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01006448
William Lallemand82fe75c2012-10-23 10:25:10 +02006449 cur_arg = 2;
6450 if (!*args[cur_arg]) {
6451 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
6452 file, linenum, args[0]);
6453 err_code |= ERR_ALERT | ERR_FATAL;
6454 goto out;
6455 }
6456 while (*(args[cur_arg])) {
6457 if (comp_append_algo(comp, args[cur_arg]) < 0) {
6458 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
6459 file, linenum, args[0], args[cur_arg]);
6460 err_code |= ERR_ALERT | ERR_FATAL;
6461 goto out;
6462 }
William Lallemand552df672012-11-07 13:21:47 +01006463 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
6464 curproxy->comp->algos->end(&ctx);
6465 } else {
6466 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
6467 file, linenum, args[0], args[cur_arg]);
6468 err_code |= ERR_ALERT | ERR_FATAL;
6469 goto out;
6470 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006471 cur_arg ++;
6472 continue;
6473 }
6474 }
Willy Tarreau70737d12012-10-27 00:34:28 +02006475 else if (!strcmp(args[1], "offload")) {
6476 comp->offload = 1;
6477 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006478 else if (!strcmp(args[1], "type")) {
6479 int cur_arg;
6480 cur_arg = 2;
6481 if (!*args[cur_arg]) {
6482 Alert("parsing [%s:%d] : '%s' expects <type>\n",
6483 file, linenum, args[0]);
6484 err_code |= ERR_ALERT | ERR_FATAL;
6485 goto out;
6486 }
6487 while (*(args[cur_arg])) {
6488 comp_append_type(comp, args[cur_arg]);
6489 cur_arg ++;
6490 continue;
6491 }
6492 }
6493 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02006494 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02006495 file, linenum, args[0]);
6496 err_code |= ERR_ALERT | ERR_FATAL;
6497 goto out;
6498 }
6499 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006500 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006501 struct cfg_kw_list *kwl;
6502 int index;
6503
6504 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6505 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6506 if (kwl->kw[index].section != CFG_LISTEN)
6507 continue;
6508 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6509 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006510 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006511 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006512 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006513 err_code |= ERR_ALERT | ERR_FATAL;
6514 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006515 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006516 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006517 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006518 err_code |= ERR_WARN;
6519 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006520 }
Willy Tarreau93893792009-07-23 13:19:11 +02006521 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006522 }
6523 }
6524 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006525
Willy Tarreau6daf3432008-01-22 16:44:08 +01006526 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006527 err_code |= ERR_ALERT | ERR_FATAL;
6528 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006529 }
Willy Tarreau93893792009-07-23 13:19:11 +02006530 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006531 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006532 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006533}
6534
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006535int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006536cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
6537{
6538#ifdef CONFIG_HAP_NS
6539 const char *err;
6540 const char *item = args[0];
6541
6542 if (!strcmp(item, "namespace_list")) {
6543 return 0;
6544 }
6545 else if (!strcmp(item, "namespace")) {
6546 size_t idx = 1;
6547 const char *current;
6548 while (*(current = args[idx++])) {
6549 err = invalid_char(current);
6550 if (err) {
6551 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6552 file, linenum, *err, item, current);
6553 return ERR_ALERT | ERR_FATAL;
6554 }
6555
6556 if (netns_store_lookup(current, strlen(current))) {
6557 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
6558 file, linenum, current);
6559 return ERR_ALERT | ERR_FATAL;
6560 }
6561 if (!netns_store_insert(current)) {
6562 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
6563 file, linenum, current);
6564 return ERR_ALERT | ERR_FATAL;
6565 }
6566 }
6567 }
6568
6569 return 0;
6570#else
6571 Alert("parsing [%s:%d]: namespace support is not compiled in.",
6572 file, linenum);
6573 return ERR_ALERT | ERR_FATAL;
6574#endif
6575}
6576
6577int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006578cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6579{
6580
6581 int err_code = 0;
6582 const char *err;
6583
6584 if (!strcmp(args[0], "userlist")) { /* new userlist */
6585 struct userlist *newul;
6586
6587 if (!*args[1]) {
6588 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6589 file, linenum, args[0]);
6590 err_code |= ERR_ALERT | ERR_FATAL;
6591 goto out;
6592 }
William Lallemand6e62fb62015-04-28 16:55:23 +02006593 if (alertif_too_many_args(1, file, linenum, args, &err_code))
6594 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006595
6596 err = invalid_char(args[1]);
6597 if (err) {
6598 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6599 file, linenum, *err, args[0], args[1]);
6600 err_code |= ERR_ALERT | ERR_FATAL;
6601 goto out;
6602 }
6603
6604 for (newul = userlist; newul; newul = newul->next)
6605 if (!strcmp(newul->name, args[1])) {
6606 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6607 file, linenum, args[1]);
6608 err_code |= ERR_WARN;
6609 goto out;
6610 }
6611
6612 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
6613 if (!newul) {
6614 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6615 err_code |= ERR_ALERT | ERR_ABORT;
6616 goto out;
6617 }
6618
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006619 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006620 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006621 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6622 err_code |= ERR_ALERT | ERR_ABORT;
6623 goto out;
6624 }
6625
6626 newul->next = userlist;
6627 userlist = newul;
6628
6629 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006630 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006631 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006632 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006633
6634 if (!*args[1]) {
6635 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6636 file, linenum, args[0]);
6637 err_code |= ERR_ALERT | ERR_FATAL;
6638 goto out;
6639 }
6640
6641 err = invalid_char(args[1]);
6642 if (err) {
6643 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6644 file, linenum, *err, args[0], args[1]);
6645 err_code |= ERR_ALERT | ERR_FATAL;
6646 goto out;
6647 }
6648
William Lallemand4ac9f542015-05-28 18:03:51 +02006649 if (!userlist)
6650 goto out;
6651
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006652 for (ag = userlist->groups; ag; ag = ag->next)
6653 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006654 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6655 file, linenum, args[1], userlist->name);
6656 err_code |= ERR_ALERT;
6657 goto out;
6658 }
6659
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006660 ag = calloc(1, sizeof(*ag));
6661 if (!ag) {
6662 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6663 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006664 goto out;
6665 }
6666
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006667 ag->name = strdup(args[1]);
6668 if (!ag) {
6669 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6670 err_code |= ERR_ALERT | ERR_ABORT;
6671 goto out;
6672 }
6673
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006674 cur_arg = 2;
6675
6676 while (*args[cur_arg]) {
6677 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006678 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006679 cur_arg += 2;
6680 continue;
6681 } else {
6682 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6683 file, linenum, args[0]);
6684 err_code |= ERR_ALERT | ERR_FATAL;
6685 goto out;
6686 }
6687 }
6688
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006689 ag->next = userlist->groups;
6690 userlist->groups = ag;
6691
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006692 } else if (!strcmp(args[0], "user")) { /* new user */
6693 struct auth_users *newuser;
6694 int cur_arg;
6695
6696 if (!*args[1]) {
6697 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6698 file, linenum, args[0]);
6699 err_code |= ERR_ALERT | ERR_FATAL;
6700 goto out;
6701 }
William Lallemand4ac9f542015-05-28 18:03:51 +02006702 if (!userlist)
6703 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006704
6705 for (newuser = userlist->users; newuser; newuser = newuser->next)
6706 if (!strcmp(newuser->user, args[1])) {
6707 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6708 file, linenum, args[1], userlist->name);
6709 err_code |= ERR_ALERT;
6710 goto out;
6711 }
6712
6713 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
6714 if (!newuser) {
6715 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6716 err_code |= ERR_ALERT | ERR_ABORT;
6717 goto out;
6718 }
6719
6720 newuser->user = strdup(args[1]);
6721
6722 newuser->next = userlist->users;
6723 userlist->users = newuser;
6724
6725 cur_arg = 2;
6726
6727 while (*args[cur_arg]) {
6728 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006729#ifdef CONFIG_HAP_CRYPT
6730 if (!crypt("", args[cur_arg + 1])) {
6731 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6732 file, linenum, newuser->user);
6733 err_code |= ERR_ALERT | ERR_FATAL;
6734 goto out;
6735 }
6736#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006737 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6738 file, linenum);
6739 err_code |= ERR_ALERT;
6740#endif
6741 newuser->pass = strdup(args[cur_arg + 1]);
6742 cur_arg += 2;
6743 continue;
6744 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6745 newuser->pass = strdup(args[cur_arg + 1]);
6746 newuser->flags |= AU_O_INSECURE;
6747 cur_arg += 2;
6748 continue;
6749 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006750 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006751 cur_arg += 2;
6752 continue;
6753 } else {
6754 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6755 file, linenum, args[0]);
6756 err_code |= ERR_ALERT | ERR_FATAL;
6757 goto out;
6758 }
6759 }
6760 } else {
6761 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6762 err_code |= ERR_ALERT | ERR_FATAL;
6763 }
6764
6765out:
6766 return err_code;
6767}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006768
6769/*
6770 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006771 * Returns the error code, 0 if OK, or any combination of :
6772 * - ERR_ABORT: must abort ASAP
6773 * - ERR_FATAL: we can continue parsing but not start the service
6774 * - ERR_WARN: a warning has been emitted
6775 * - ERR_ALERT: an alert has been emitted
6776 * Only the two first ones can stop processing, the two others are just
6777 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006778 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006779int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006780{
William Lallemand64e84512015-05-12 14:25:37 +02006781 char *thisline;
6782 int linesize = LINESIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006783 FILE *f;
6784 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02006785 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006786 struct cfg_section *cs = NULL;
6787 struct cfg_section *ics;
William Lallemand64e84512015-05-12 14:25:37 +02006788 int readbytes = 0;
6789
6790 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
William Lallemandb2f07452015-05-12 14:27:13 +02006791 Alert("parsing [%s] : out of memory.\n", file);
William Lallemand64e84512015-05-12 14:25:37 +02006792 return -1;
6793 }
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006794
6795 /* Register internal sections */
6796 if (!cfg_register_section("listen", cfg_parse_listen) ||
6797 !cfg_register_section("frontend", cfg_parse_listen) ||
6798 !cfg_register_section("backend", cfg_parse_listen) ||
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006799 !cfg_register_section("defaults", cfg_parse_listen) ||
6800 !cfg_register_section("global", cfg_parse_global) ||
6801 !cfg_register_section("userlist", cfg_parse_users) ||
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006802 !cfg_register_section("peers", cfg_parse_peers) ||
Simon Horman0d16a402015-01-30 11:22:58 +09006803 !cfg_register_section("mailers", cfg_parse_mailers) ||
Baptiste Assmann325137d2015-04-13 23:40:55 +02006804 !cfg_register_section("namespace_list", cfg_parse_netns) ||
6805 !cfg_register_section("resolvers", cfg_parse_resolvers))
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006806 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006807
Willy Tarreaubaaee002006-06-26 02:48:02 +02006808 if ((f=fopen(file,"r")) == NULL)
6809 return -1;
6810
William Lallemandb2f07452015-05-12 14:27:13 +02006811next_line:
William Lallemand64e84512015-05-12 14:25:37 +02006812 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02006813 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006814 char *end;
6815 char *args[MAX_LINE_ARGS + 1];
6816 char *line = thisline;
William Lallemandf9873ba2015-05-05 17:37:14 +02006817 int dquote = 0; /* double quote */
6818 int squote = 0; /* simple quote */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006819
Willy Tarreaubaaee002006-06-26 02:48:02 +02006820 linenum++;
6821
6822 end = line + strlen(line);
6823
William Lallemand64e84512015-05-12 14:25:37 +02006824 if (end-line == linesize-1 && *(end-1) != '\n') {
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006825 /* Check if we reached the limit and the last char is not \n.
6826 * Watch out for the last line without the terminating '\n'!
6827 */
William Lallemand64e84512015-05-12 14:25:37 +02006828 char *newline;
6829 int newlinesize = linesize * 2;
6830
6831 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
6832 if (newline == NULL) {
6833 Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
6834 file, linenum);
6835 err_code |= ERR_ALERT | ERR_FATAL;
6836 continue;
6837 }
6838
6839 readbytes = linesize - 1;
6840 linesize = newlinesize;
6841 thisline = newline;
6842 continue;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006843 }
6844
William Lallemand64e84512015-05-12 14:25:37 +02006845 readbytes = 0;
6846
Willy Tarreaubaaee002006-06-26 02:48:02 +02006847 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006848 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006849 line++;
William Lallemandf9873ba2015-05-05 17:37:14 +02006850
Willy Tarreaubaaee002006-06-26 02:48:02 +02006851 arg = 0;
6852 args[arg] = line;
6853
6854 while (*line && arg < MAX_LINE_ARGS) {
William Lallemandf9873ba2015-05-05 17:37:14 +02006855 if (*line == '"' && !squote) { /* double quote outside single quotes */
6856 if (dquote)
6857 dquote = 0;
6858 else
6859 dquote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02006860 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02006861 end--;
6862 }
6863 else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
6864 if (squote)
6865 squote = 0;
6866 else
6867 squote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02006868 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02006869 end--;
6870 }
6871 else if (*line == '\\' && !squote) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006872 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
6873 * C equivalent value. Other combinations left unchanged (eg: \1).
6874 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006875 int skip = 0;
6876 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
6877 *line = line[1];
6878 skip = 1;
6879 }
6880 else if (line[1] == 'r') {
6881 *line = '\r';
6882 skip = 1;
William Lallemandf9873ba2015-05-05 17:37:14 +02006883 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006884 else if (line[1] == 'n') {
6885 *line = '\n';
6886 skip = 1;
6887 }
6888 else if (line[1] == 't') {
6889 *line = '\t';
6890 skip = 1;
6891 }
6892 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01006893 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006894 unsigned char hex1, hex2;
6895 hex1 = toupper(line[2]) - '0';
6896 hex2 = toupper(line[3]) - '0';
6897 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
6898 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
6899 *line = (hex1<<4) + hex2;
6900 skip = 3;
6901 }
6902 else {
6903 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006904 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006905 }
William Lallemandf9873ba2015-05-05 17:37:14 +02006906 } else if (line[1] == '"') {
6907 *line = '"';
6908 skip = 1;
6909 } else if (line[1] == '\'') {
6910 *line = '\'';
6911 skip = 1;
William Lallemandb2f07452015-05-12 14:27:13 +02006912 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
6913 *line = '$';
6914 skip = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006915 }
6916 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01006917 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006918 end -= skip;
6919 }
6920 line++;
6921 }
William Lallemandf9873ba2015-05-05 17:37:14 +02006922 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006923 /* end of string, end of loop */
6924 *line = 0;
6925 break;
6926 }
William Lallemandf9873ba2015-05-05 17:37:14 +02006927 else if (!squote && !dquote && isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006928 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006929 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006930 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006931 line++;
6932 args[++arg] = line;
6933 }
William Lallemandb2f07452015-05-12 14:27:13 +02006934 else if (dquote && *line == '$') {
6935 /* environment variables are evaluated inside double quotes */
6936 char *var_beg;
6937 char *var_end;
6938 char save_char;
6939 char *value;
6940 int val_len;
6941 int newlinesize;
6942 int braces = 0;
6943
6944 var_beg = line + 1;
6945 var_end = var_beg;
6946
6947 if (*var_beg == '{') {
6948 var_beg++;
6949 var_end++;
6950 braces = 1;
6951 }
6952
6953 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
6954 Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
6955 err_code |= ERR_ALERT | ERR_FATAL;
6956 goto next_line; /* skip current line */
6957 }
6958
6959 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
6960 var_end++;
6961
6962 save_char = *var_end;
6963 *var_end = '\0';
6964 value = getenv(var_beg);
6965 *var_end = save_char;
6966 val_len = value ? strlen(value) : 0;
6967
6968 if (braces) {
6969 if (*var_end == '}') {
6970 var_end++;
6971 braces = 0;
6972 } else {
6973 Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
6974 err_code |= ERR_ALERT | ERR_FATAL;
6975 goto next_line; /* skip current line */
6976 }
6977 }
6978
6979 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
6980
6981 /* if not enough space in thisline */
6982 if (newlinesize > linesize) {
6983 char *newline;
6984
6985 newline = realloc(thisline, newlinesize * sizeof(*thisline));
6986 if (newline == NULL) {
6987 Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
6988 err_code |= ERR_ALERT | ERR_FATAL;
6989 goto next_line; /* slip current line */
6990 }
6991 /* recompute pointers if realloc returns a new pointer */
6992 if (newline != thisline) {
6993 int i;
6994 int diff;
6995
6996 for (i = 0; i <= arg; i++) {
6997 diff = args[i] - thisline;
6998 args[i] = newline + diff;
6999 }
7000
7001 diff = var_end - thisline;
7002 var_end = newline + diff;
7003 diff = end - thisline;
7004 end = newline + diff;
7005 diff = line - thisline;
7006 line = newline + diff;
7007 thisline = newline;
7008 }
7009 linesize = newlinesize;
7010 }
7011
7012 /* insert value inside the line */
7013 memmove(line + val_len, var_end, end - var_end + 1);
7014 memcpy(line, value, val_len);
7015 end += val_len - (var_end - line);
7016 line += val_len;
7017 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007018 else {
7019 line++;
7020 }
7021 }
William Lallemandb2f07452015-05-12 14:27:13 +02007022
William Lallemandf9873ba2015-05-05 17:37:14 +02007023 if (dquote) {
7024 Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
7025 err_code |= ERR_ALERT | ERR_FATAL;
7026 }
7027
7028 if (squote) {
7029 Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
7030 err_code |= ERR_ALERT | ERR_FATAL;
7031 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007032
7033 /* empty line */
7034 if (!**args)
7035 continue;
7036
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007037 if (*line) {
7038 /* we had to stop due to too many args.
7039 * Let's terminate the string, print the offending part then cut the
7040 * last arg.
7041 */
7042 while (*line && *line != '#' && *line != '\n' && *line != '\r')
7043 line++;
7044 *line = '\0';
7045
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01007046 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01007047 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007048 err_code |= ERR_ALERT | ERR_FATAL;
7049 args[arg] = line;
7050 }
7051
Willy Tarreau540abe42007-05-02 20:50:16 +02007052 /* zero out remaining args and ensure that at least one entry
7053 * is zeroed out.
7054 */
7055 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007056 args[arg] = line;
7057 }
7058
Willy Tarreau3842f002009-06-14 11:39:52 +02007059 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007060 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02007061 char *tmp;
7062
Willy Tarreau3842f002009-06-14 11:39:52 +02007063 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02007064 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007065 for (arg=0; *args[arg+1]; arg++)
7066 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02007067 *tmp = '\0'; // fix the next arg to \0
7068 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007069 }
Willy Tarreau3842f002009-06-14 11:39:52 +02007070 else if (!strcmp(args[0], "default")) {
7071 kwm = KWM_DEF;
7072 for (arg=0; *args[arg+1]; arg++)
7073 args[arg] = args[arg+1]; // shift args after inversion
7074 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007075
William Lallemand0f99e342011-10-12 17:50:54 +02007076 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
7077 strcmp(args[0], "log") != 0) {
7078 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02007079 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007080 }
7081
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007082 /* detect section start */
7083 list_for_each_entry(ics, &sections, list) {
7084 if (strcmp(args[0], ics->section_name) == 0) {
7085 cursection = ics->section_name;
7086 cs = ics;
7087 break;
7088 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007089 }
7090
Willy Tarreaubaaee002006-06-26 02:48:02 +02007091 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007092 if (cs)
7093 err_code |= cs->section_parser(file, linenum, args, kwm);
7094 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007095 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007096 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007097 }
Willy Tarreau058e9072009-07-20 09:30:05 +02007098
7099 if (err_code & ERR_ABORT)
7100 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007101 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01007102 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02007103 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007104 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02007105 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007106}
7107
Willy Tarreau64ab6072014-09-16 12:17:36 +02007108/* This function propagates processes from frontend <from> to backend <to> so
7109 * that it is always guaranteed that a backend pointed to by a frontend is
7110 * bound to all of its processes. After that, if the target is a "listen"
7111 * instance, the function recursively descends the target's own targets along
Willy Tarreau98d04852015-05-26 12:18:29 +02007112 * default_backend and use_backend rules. Since the bits are
Willy Tarreau64ab6072014-09-16 12:17:36 +02007113 * checked first to ensure that <to> is already bound to all processes of
7114 * <from>, there is no risk of looping and we ensure to follow the shortest
7115 * path to the destination.
7116 *
7117 * It is possible to set <to> to NULL for the first call so that the function
7118 * takes care of visiting the initial frontend in <from>.
7119 *
7120 * It is important to note that the function relies on the fact that all names
7121 * have already been resolved.
7122 */
7123void propagate_processes(struct proxy *from, struct proxy *to)
7124{
7125 struct switching_rule *rule;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007126
7127 if (to) {
7128 /* check whether we need to go down */
7129 if (from->bind_proc &&
7130 (from->bind_proc & to->bind_proc) == from->bind_proc)
7131 return;
7132
7133 if (!from->bind_proc && !to->bind_proc)
7134 return;
7135
7136 to->bind_proc = from->bind_proc ?
7137 (to->bind_proc | from->bind_proc) : 0;
7138
7139 /* now propagate down */
7140 from = to;
7141 }
7142
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01007143 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02007144 return;
7145
Willy Tarreauf6b70012014-12-18 14:00:43 +01007146 if (from->state == PR_STSTOPPED)
7147 return;
7148
Willy Tarreau64ab6072014-09-16 12:17:36 +02007149 /* default_backend */
7150 if (from->defbe.be)
7151 propagate_processes(from, from->defbe.be);
7152
7153 /* use_backend */
7154 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02007155 if (rule->dynamic)
7156 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007157 to = rule->be.backend;
7158 propagate_processes(from, to);
7159 }
Willy Tarreau64ab6072014-09-16 12:17:36 +02007160}
7161
Willy Tarreaubb925012009-07-23 13:36:36 +02007162/*
7163 * Returns the error code, 0 if OK, or any combination of :
7164 * - ERR_ABORT: must abort ASAP
7165 * - ERR_FATAL: we can continue parsing but not start the service
7166 * - ERR_WARN: a warning has been emitted
7167 * - ERR_ALERT: an alert has been emitted
7168 * Only the two first ones can stop processing, the two others are just
7169 * indicators.
7170 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007171int check_config_validity()
7172{
7173 int cfgerr = 0;
7174 struct proxy *curproxy = NULL;
7175 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02007176 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007177 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007178 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007179
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007180 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007181 /*
7182 * Now, check for the integrity of all that we have collected.
7183 */
7184
7185 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02007186 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007187
Willy Tarreau193b8c62012-11-22 00:17:38 +01007188 if (!global.tune.max_http_hdr)
7189 global.tune.max_http_hdr = MAX_HTTP_HDR;
7190
7191 if (!global.tune.cookie_len)
7192 global.tune.cookie_len = CAPTURE_LEN;
7193
7194 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
7195
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007196 /* Post initialisation of the users and groups lists. */
7197 err_code = userlist_postinit();
7198 if (err_code != ERR_NONE)
7199 goto out;
7200
Willy Tarreau55bc0f82009-03-15 14:51:53 +01007201 /* first, we will invert the proxy list order */
7202 curproxy = NULL;
7203 while (proxy) {
7204 struct proxy *next;
7205
7206 next = proxy->next;
7207 proxy->next = curproxy;
7208 curproxy = proxy;
7209 if (!next)
7210 break;
7211 proxy = next;
7212 }
7213
Willy Tarreau419ead82014-09-16 13:41:21 +02007214 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007215 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007216 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01007217 struct sticking_rule *mrule;
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007218 struct act_rule *trule;
7219 struct act_rule *hrqrule;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007220 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01007221 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007222
Willy Tarreau050536d2012-10-04 08:47:34 +02007223 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007224 /* proxy ID not set, use automatic numbering with first
7225 * spare entry starting with next_pxid.
7226 */
7227 next_pxid = get_next_id(&used_proxy_id, next_pxid);
7228 curproxy->conf.id.key = curproxy->uuid = next_pxid;
7229 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007230 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007231 next_pxid++;
7232
Willy Tarreau55ea7572007-06-17 19:56:27 +02007233
Willy Tarreaubaaee002006-06-26 02:48:02 +02007234 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02007235 /* ensure we don't keep listeners uselessly bound */
7236 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02007237 free((void *)curproxy->table.peers.name);
7238 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007239 continue;
7240 }
7241
Willy Tarreau102df612014-05-07 23:56:38 +02007242 /* Check multi-process mode compatibility for the current proxy */
7243
7244 if (curproxy->bind_proc) {
7245 /* an explicit bind-process was specified, let's check how many
7246 * processes remain.
7247 */
David Carliere6c39412015-07-02 07:00:17 +00007248 nbproc = my_popcountl(curproxy->bind_proc);
Willy Tarreau102df612014-05-07 23:56:38 +02007249
7250 curproxy->bind_proc &= nbits(global.nbproc);
7251 if (!curproxy->bind_proc && nbproc == 1) {
7252 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);
7253 curproxy->bind_proc = 1;
7254 }
7255 else if (!curproxy->bind_proc && nbproc > 1) {
7256 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);
7257 curproxy->bind_proc = 0;
7258 }
7259 }
7260
Willy Tarreau3d209582014-05-09 17:06:11 +02007261 /* check and reduce the bind-proc of each listener */
7262 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7263 unsigned long mask;
7264
7265 if (!bind_conf->bind_proc)
7266 continue;
7267
7268 mask = nbits(global.nbproc);
7269 if (curproxy->bind_proc)
7270 mask &= curproxy->bind_proc;
7271 /* mask cannot be null here thanks to the previous checks */
7272
David Carliere6c39412015-07-02 07:00:17 +00007273 nbproc = my_popcountl(bind_conf->bind_proc);
Willy Tarreau3d209582014-05-09 17:06:11 +02007274 bind_conf->bind_proc &= mask;
7275
7276 if (!bind_conf->bind_proc && nbproc == 1) {
7277 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",
7278 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7279 bind_conf->bind_proc = mask & ~(mask - 1);
7280 }
7281 else if (!bind_conf->bind_proc && nbproc > 1) {
7282 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",
7283 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7284 bind_conf->bind_proc = 0;
7285 }
7286 }
7287
Willy Tarreauff01a212009-03-15 13:46:16 +01007288 switch (curproxy->mode) {
7289 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007290 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007291 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007292 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
7293 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007294 cfgerr++;
7295 }
7296
7297 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007298 Warning("config : servers will be ignored for %s '%s'.\n",
7299 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007300 break;
7301
7302 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007303 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007304 break;
7305
7306 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01007307 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01007308 break;
7309 }
7310
Willy Tarreauf3934b82015-08-11 11:36:45 +02007311 if ((curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->conf.listeners)) {
7312 Warning("config : %s '%s' has no 'bind' directive. Please declare it as a backend if this was intended.\n",
7313 proxy_type_str(curproxy), curproxy->id);
7314 err_code |= ERR_WARN;
7315 }
7316
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007317 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007318 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007319 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007320 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
7321 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007322 cfgerr++;
7323 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007324#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007325 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007326 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
7327 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007328 cfgerr++;
7329 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007330#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02007331 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007332 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
7333 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007334 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007335 }
7336 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02007337 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007338 /* If no LB algo is set in a backend, and we're not in
7339 * transparent mode, dispatch mode nor proxy mode, we
7340 * want to use balance roundrobin by default.
7341 */
7342 curproxy->lbprm.algo &= ~BE_LB_ALGO;
7343 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007344 }
7345 }
Willy Tarreau193cf932007-09-17 10:17:23 +02007346
Willy Tarreau1620ec32011-08-06 17:05:02 +02007347 if (curproxy->options & PR_O_DISPATCH)
7348 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
7349 else if (curproxy->options & PR_O_HTTP_PROXY)
7350 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
7351 else if (curproxy->options & PR_O_TRANSP)
7352 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01007353
Willy Tarreau1620ec32011-08-06 17:05:02 +02007354 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
7355 if (curproxy->options & PR_O_DISABLE404) {
7356 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7357 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
7358 err_code |= ERR_WARN;
7359 curproxy->options &= ~PR_O_DISABLE404;
7360 }
7361 if (curproxy->options2 & PR_O2_CHK_SNDST) {
7362 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7363 "send-state", proxy_type_str(curproxy), curproxy->id);
7364 err_code |= ERR_WARN;
7365 curproxy->options &= ~PR_O2_CHK_SNDST;
7366 }
Willy Tarreauef781042010-01-27 11:53:01 +01007367 }
7368
Simon Horman98637e52014-06-20 12:30:16 +09007369 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
7370 if (!global.external_check) {
7371 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
7372 curproxy->id, "option external-check");
7373 cfgerr++;
7374 }
7375 if (!curproxy->check_command) {
7376 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
7377 curproxy->id, "option external-check");
7378 cfgerr++;
7379 }
7380 }
7381
Simon Horman64e34162015-02-06 11:11:57 +09007382 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007383 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
7384 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Pieter Baauw8669e972015-08-17 00:45:05 +02007385 "'email-alert from', 'email-alert level' 'email-alert mailers', "
7386 "'email-alert myhostname', or 'email-alert to' "
7387 "requires each of 'email-alert from', 'email-alert mailers' and 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007388 "to be present).\n",
7389 proxy_type_str(curproxy), curproxy->id);
7390 err_code |= ERR_WARN;
7391 free_email_alert(curproxy);
7392 }
7393 if (!curproxy->email_alert.myhostname)
7394 curproxy->email_alert.myhostname = hostname;
Simon Horman9dc49962015-01-30 11:22:59 +09007395 }
7396
Simon Horman98637e52014-06-20 12:30:16 +09007397 if (curproxy->check_command) {
7398 int clear = 0;
7399 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7400 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7401 "external-check command", proxy_type_str(curproxy), curproxy->id);
7402 err_code |= ERR_WARN;
7403 clear = 1;
7404 }
7405 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
7406 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-command path' is not set.\n",
7407 curproxy->id, "external-check command");
7408 cfgerr++;
7409 }
7410 if (clear) {
7411 free(curproxy->check_command);
7412 curproxy->check_command = NULL;
7413 }
7414 }
7415
7416 if (curproxy->check_path) {
7417 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7418 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7419 "external-check path", proxy_type_str(curproxy), curproxy->id);
7420 err_code |= ERR_WARN;
7421 free(curproxy->check_path);
7422 curproxy->check_path = NULL;
7423 }
7424 }
7425
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007426 /* if a default backend was specified, let's find it */
7427 if (curproxy->defbe.name) {
7428 struct proxy *target;
7429
Willy Tarreauafb39922015-05-26 12:04:09 +02007430 target = proxy_be_by_name(curproxy->defbe.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007431 if (!target) {
7432 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
7433 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007434 cfgerr++;
7435 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007436 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
7437 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02007438 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007439 } else if (target->mode != curproxy->mode &&
7440 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7441
7442 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) as its default backend (see 'mode').\n",
7443 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7444 curproxy->conf.file, curproxy->conf.line,
7445 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7446 target->conf.file, target->conf.line);
7447 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007448 } else {
7449 free(curproxy->defbe.name);
7450 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01007451
7452 /* Emit a warning if this proxy also has some servers */
7453 if (curproxy->srv) {
7454 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
7455 curproxy->id);
7456 err_code |= ERR_WARN;
7457 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007458 }
7459 }
7460
Willy Tarreau55ea7572007-06-17 19:56:27 +02007461 /* find the target proxy for 'use_backend' rules */
7462 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007463 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007464 struct logformat_node *node;
7465 char *pxname;
7466
7467 /* Try to parse the string as a log format expression. If the result
7468 * of the parsing is only one entry containing a simple string, then
7469 * it's a standard string corresponding to a static rule, thus the
7470 * parsing is cancelled and be.name is restored to be resolved.
7471 */
7472 pxname = rule->be.name;
7473 LIST_INIT(&rule->be.expr);
7474 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
7475 curproxy->conf.args.file, curproxy->conf.args.line);
7476 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
7477
7478 if (!LIST_ISEMPTY(&rule->be.expr)) {
7479 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
7480 rule->dynamic = 1;
7481 free(pxname);
7482 continue;
7483 }
7484 /* simple string: free the expression and fall back to static rule */
7485 free(node->arg);
7486 free(node);
7487 }
7488
7489 rule->dynamic = 0;
7490 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007491
Willy Tarreauafb39922015-05-26 12:04:09 +02007492 target = proxy_be_by_name(rule->be.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007493 if (!target) {
7494 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
7495 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007496 cfgerr++;
7497 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007498 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
7499 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007500 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007501 } else if (target->mode != curproxy->mode &&
7502 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7503
7504 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) in a 'use_backend' rule (see 'mode').\n",
7505 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7506 curproxy->conf.file, curproxy->conf.line,
7507 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7508 target->conf.file, target->conf.line);
7509 cfgerr++;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007510 } else {
7511 free((void *)rule->be.name);
7512 rule->be.backend = target;
7513 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007514 }
7515
Willy Tarreau64ab6072014-09-16 12:17:36 +02007516 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007517 list_for_each_entry(srule, &curproxy->server_rules, list) {
7518 struct server *target = findserver(curproxy, srule->srv.name);
7519
7520 if (!target) {
7521 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7522 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7523 cfgerr++;
7524 continue;
7525 }
7526 free((void *)srule->srv.name);
7527 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007528 }
7529
Emeric Brunb982a3d2010-01-04 15:45:53 +01007530 /* find the target table for 'stick' rules */
7531 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7532 struct proxy *target;
7533
Emeric Brun1d33b292010-01-04 15:47:17 +01007534 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7535 if (mrule->flags & STK_IS_STORE)
7536 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7537
Emeric Brunb982a3d2010-01-04 15:45:53 +01007538 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007539 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007540 else
7541 target = curproxy;
7542
7543 if (!target) {
7544 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7545 curproxy->id, mrule->table.name);
7546 cfgerr++;
7547 }
7548 else if (target->table.size == 0) {
7549 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7550 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7551 cfgerr++;
7552 }
Willy Tarreau12785782012-04-27 21:37:17 +02007553 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7554 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007555 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7556 cfgerr++;
7557 }
7558 else {
7559 free((void *)mrule->table.name);
7560 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007561 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007562 }
7563 }
7564
7565 /* find the target table for 'store response' rules */
7566 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7567 struct proxy *target;
7568
Emeric Brun1d33b292010-01-04 15:47:17 +01007569 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7570
Emeric Brunb982a3d2010-01-04 15:45:53 +01007571 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007572 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007573 else
7574 target = curproxy;
7575
7576 if (!target) {
7577 Alert("Proxy '%s': unable to find store table '%s'.\n",
7578 curproxy->id, mrule->table.name);
7579 cfgerr++;
7580 }
7581 else if (target->table.size == 0) {
7582 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7583 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7584 cfgerr++;
7585 }
Willy Tarreau12785782012-04-27 21:37:17 +02007586 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7587 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007588 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7589 cfgerr++;
7590 }
7591 else {
7592 free((void *)mrule->table.name);
7593 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007594 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007595 }
7596 }
7597
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007598 /* find the target table for 'tcp-request' layer 4 rules */
7599 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
7600 struct proxy *target;
7601
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007602 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007603 continue;
7604
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007605 if (trule->arg.trk_ctr.table.n)
7606 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007607 else
7608 target = curproxy;
7609
7610 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007611 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007612 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007613 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007614 cfgerr++;
7615 }
7616 else if (target->table.size == 0) {
7617 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007618 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007619 cfgerr++;
7620 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007621 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007622 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007623 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007624 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007625 cfgerr++;
7626 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007627 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007628 free(trule->arg.trk_ctr.table.n);
7629 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007630 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007631 * to pass a list of counters to track and allocate them right here using
7632 * stktable_alloc_data_type().
7633 */
7634 }
7635 }
7636
Willy Tarreaud1f96522010-08-03 19:34:32 +02007637 /* find the target table for 'tcp-request' layer 6 rules */
7638 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7639 struct proxy *target;
7640
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007641 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02007642 continue;
7643
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007644 if (trule->arg.trk_ctr.table.n)
7645 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007646 else
7647 target = curproxy;
7648
7649 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007650 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007651 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007652 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02007653 cfgerr++;
7654 }
7655 else if (target->table.size == 0) {
7656 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007657 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007658 cfgerr++;
7659 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007660 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007661 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007662 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007663 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007664 cfgerr++;
7665 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02007666 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007667 free(trule->arg.trk_ctr.table.n);
7668 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007669 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02007670 * to pass a list of counters to track and allocate them right here using
7671 * stktable_alloc_data_type().
7672 */
7673 }
7674 }
7675
Willy Tarreau09448f72014-06-25 18:12:15 +02007676 /* find the target table for 'http-request' layer 7 rules */
7677 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7678 struct proxy *target;
7679
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007680 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau09448f72014-06-25 18:12:15 +02007681 continue;
7682
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007683 if (hrqrule->arg.trk_ctr.table.n)
7684 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
Willy Tarreau09448f72014-06-25 18:12:15 +02007685 else
7686 target = curproxy;
7687
7688 if (!target) {
7689 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007690 curproxy->id, hrqrule->arg.trk_ctr.table.n,
Willy Tarreau09448f72014-06-25 18:12:15 +02007691 http_req_trk_idx(hrqrule->action));
7692 cfgerr++;
7693 }
7694 else if (target->table.size == 0) {
7695 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007696 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau09448f72014-06-25 18:12:15 +02007697 cfgerr++;
7698 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007699 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau09448f72014-06-25 18:12:15 +02007700 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007701 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau09448f72014-06-25 18:12:15 +02007702 http_req_trk_idx(hrqrule->action));
7703 cfgerr++;
7704 }
7705 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007706 free(hrqrule->arg.trk_ctr.table.n);
7707 hrqrule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau09448f72014-06-25 18:12:15 +02007708 /* Note: if we decide to enhance the track-sc syntax, we may be able
7709 * to pass a list of counters to track and allocate them right here using
7710 * stktable_alloc_data_type().
7711 */
7712 }
7713 }
7714
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02007715 /* move any "block" rules at the beginning of the http-request rules */
7716 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
7717 /* insert block_rules into http_req_rules at the beginning */
7718 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
7719 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
7720 curproxy->block_rules.n->p = &curproxy->http_req_rules;
7721 curproxy->http_req_rules.n = curproxy->block_rules.n;
7722 LIST_INIT(&curproxy->block_rules);
7723 }
7724
Emeric Brun32da3c42010-09-23 18:39:19 +02007725 if (curproxy->table.peers.name) {
7726 struct peers *curpeers = peers;
7727
7728 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
7729 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
7730 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01007731 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02007732 break;
7733 }
7734 }
7735
7736 if (!curpeers) {
7737 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
7738 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007739 free((void *)curproxy->table.peers.name);
7740 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007741 cfgerr++;
7742 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02007743 else if (curpeers->state == PR_STSTOPPED) {
7744 /* silently disable this peers section */
7745 curproxy->table.peers.p = NULL;
7746 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007747 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02007748 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
7749 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007750 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007751 cfgerr++;
7752 }
7753 }
7754
Simon Horman9dc49962015-01-30 11:22:59 +09007755
7756 if (curproxy->email_alert.mailers.name) {
7757 struct mailers *curmailers = mailers;
7758
7759 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
7760 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
7761 free(curproxy->email_alert.mailers.name);
7762 curproxy->email_alert.mailers.m = curmailers;
7763 curmailers->users++;
7764 break;
7765 }
7766 }
7767
7768 if (!curmailers) {
7769 Alert("Proxy '%s': unable to find mailers '%s'.\n",
7770 curproxy->id, curproxy->email_alert.mailers.name);
7771 free_email_alert(curproxy);
7772 cfgerr++;
7773 }
7774 }
7775
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007776 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01007777 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007778 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
7779 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
7780 "proxy", curproxy->id);
7781 cfgerr++;
7782 goto out_uri_auth_compat;
7783 }
7784
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007785 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007786 const char *uri_auth_compat_req[10];
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007787 struct act_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01007788 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007789
Willy Tarreau95fa4692010-02-01 13:05:50 +01007790 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
7791 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007792
7793 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007794 uri_auth_compat_req[i++] = "realm";
7795 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
7796 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007797
Willy Tarreau95fa4692010-02-01 13:05:50 +01007798 uri_auth_compat_req[i++] = "unless";
7799 uri_auth_compat_req[i++] = "{";
7800 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
7801 uri_auth_compat_req[i++] = "}";
7802 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007803
Willy Tarreauff011f22011-01-06 17:51:27 +01007804 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
7805 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007806 cfgerr++;
7807 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007808 }
7809
Willy Tarreauff011f22011-01-06 17:51:27 +01007810 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01007811
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007812 if (curproxy->uri_auth->auth_realm) {
7813 free(curproxy->uri_auth->auth_realm);
7814 curproxy->uri_auth->auth_realm = NULL;
7815 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007816
7817 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007818 }
7819out_uri_auth_compat:
7820
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007821 /* compile the log format */
7822 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02007823 if (curproxy->conf.logformat_string != default_http_log_format &&
7824 curproxy->conf.logformat_string != default_tcp_log_format &&
7825 curproxy->conf.logformat_string != clf_http_log_format)
7826 free(curproxy->conf.logformat_string);
7827 curproxy->conf.logformat_string = NULL;
7828 free(curproxy->conf.lfs_file);
7829 curproxy->conf.lfs_file = NULL;
7830 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007831 }
7832
Willy Tarreau62a61232013-04-12 18:13:46 +02007833 if (curproxy->conf.logformat_string) {
7834 curproxy->conf.args.ctx = ARGC_LOG;
7835 curproxy->conf.args.file = curproxy->conf.lfs_file;
7836 curproxy->conf.args.line = curproxy->conf.lfs_line;
7837 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007838 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007839 curproxy->conf.args.file = NULL;
7840 curproxy->conf.args.line = 0;
7841 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007842
Willy Tarreau62a61232013-04-12 18:13:46 +02007843 if (curproxy->conf.uniqueid_format_string) {
7844 curproxy->conf.args.ctx = ARGC_UIF;
7845 curproxy->conf.args.file = curproxy->conf.uif_file;
7846 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01007847 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Godbachd9722032014-12-18 15:44:58 +08007848 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007849 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007850 curproxy->conf.args.file = NULL;
7851 curproxy->conf.args.line = 0;
7852 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007853
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007854 /* only now we can check if some args remain unresolved.
7855 * This must be done after the users and groups resolution.
7856 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007857 cfgerr += smp_resolve_args(curproxy);
7858 if (!cfgerr)
7859 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01007860
Willy Tarreau2738a142006-07-08 17:28:09 +02007861 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007862 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02007863 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02007864 (!curproxy->timeout.connect ||
7865 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007866 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02007867 " | While not properly invalid, you will certainly encounter various problems\n"
7868 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01007869 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007870 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007871 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02007872 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02007873
Willy Tarreau1fa31262007-12-03 00:36:16 +01007874 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
7875 * We must still support older configurations, so let's find out whether those
7876 * parameters have been set or must be copied from contimeouts.
7877 */
7878 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007879 if (!curproxy->timeout.tarpit ||
7880 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007881 /* tarpit timeout not set. We search in the following order:
7882 * default.tarpit, curr.connect, default.connect.
7883 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007884 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007885 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007886 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007887 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007888 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007889 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007890 }
7891 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007892 (!curproxy->timeout.queue ||
7893 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007894 /* queue timeout not set. We search in the following order:
7895 * default.queue, curr.connect, default.connect.
7896 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007897 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007898 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007899 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007900 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007901 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007902 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007903 }
7904 }
7905
Willy Tarreau1620ec32011-08-06 17:05:02 +02007906 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01007907 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
7908 curproxy->check_req = (char *)malloc(curproxy->check_len);
7909 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02007910 }
7911
Willy Tarreau215663d2014-06-13 18:30:23 +02007912 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
7913 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
7914 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
7915 proxy_type_str(curproxy), curproxy->id);
7916 err_code |= ERR_WARN;
7917 }
7918
Willy Tarreau193b8c62012-11-22 00:17:38 +01007919 /* ensure that cookie capture length is not too large */
7920 if (curproxy->capture_len >= global.tune.cookie_len) {
7921 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
7922 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
7923 err_code |= ERR_WARN;
7924 curproxy->capture_len = global.tune.cookie_len - 1;
7925 }
7926
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007927 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01007928 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02007929 curproxy->req_cap_pool = create_pool("ptrcap",
7930 curproxy->nb_req_cap * sizeof(char *),
7931 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01007932 }
7933
7934 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02007935 curproxy->rsp_cap_pool = create_pool("ptrcap",
7936 curproxy->nb_rsp_cap * sizeof(char *),
7937 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01007938 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007939
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02007940 switch (curproxy->load_server_state_from_file) {
7941 case PR_SRV_STATE_FILE_UNSPEC:
7942 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
7943 break;
7944 case PR_SRV_STATE_FILE_GLOBAL:
7945 if (!global.server_state_file) {
7946 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",
7947 curproxy->id);
7948 err_code |= ERR_WARN;
7949 }
7950 break;
7951 }
7952
Willy Tarreaubaaee002006-06-26 02:48:02 +02007953 /* first, we will invert the servers list order */
7954 newsrv = NULL;
7955 while (curproxy->srv) {
7956 struct server *next;
7957
7958 next = curproxy->srv->next;
7959 curproxy->srv->next = newsrv;
7960 newsrv = curproxy->srv;
7961 if (!next)
7962 break;
7963 curproxy->srv = next;
7964 }
7965
Willy Tarreau17edc812014-01-03 12:14:34 +01007966 /* Check that no server name conflicts. This causes trouble in the stats.
7967 * We only emit a warning for the first conflict affecting each server,
7968 * in order to avoid combinatory explosion if all servers have the same
7969 * name. We do that only for servers which do not have an explicit ID,
7970 * because these IDs were made also for distinguishing them and we don't
7971 * want to annoy people who correctly manage them.
7972 */
7973 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
7974 struct server *other_srv;
7975
7976 if (newsrv->puid)
7977 continue;
7978
7979 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
7980 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
7981 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
7982 newsrv->conf.file, newsrv->conf.line,
7983 proxy_type_str(curproxy), curproxy->id,
7984 newsrv->id, other_srv->conf.line);
7985 break;
7986 }
7987 }
7988 }
7989
Willy Tarreaudd701652010-05-25 23:03:02 +02007990 /* assign automatic UIDs to servers which don't have one yet */
7991 next_id = 1;
7992 newsrv = curproxy->srv;
7993 while (newsrv != NULL) {
7994 if (!newsrv->puid) {
7995 /* server ID not set, use automatic numbering with first
7996 * spare entry starting with next_svid.
7997 */
7998 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
7999 newsrv->conf.id.key = newsrv->puid = next_id;
8000 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
8001 }
8002 next_id++;
8003 newsrv = newsrv->next;
8004 }
8005
Willy Tarreau20697042007-11-15 23:26:18 +01008006 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01008007 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02008008
Willy Tarreau62c3be22012-01-20 13:12:32 +01008009 /*
8010 * If this server supports a maxconn parameter, it needs a dedicated
8011 * tasks to fill the emptied slots when a connection leaves.
8012 * Also, resolve deferred tracking dependency if needed.
8013 */
8014 newsrv = curproxy->srv;
8015 while (newsrv != NULL) {
8016 if (newsrv->minconn > newsrv->maxconn) {
8017 /* Only 'minconn' was specified, or it was higher than or equal
8018 * to 'maxconn'. Let's turn this into maxconn and clean it, as
8019 * this will avoid further useless expensive computations.
8020 */
8021 newsrv->maxconn = newsrv->minconn;
8022 } else if (newsrv->maxconn && !newsrv->minconn) {
8023 /* minconn was not specified, so we set it to maxconn */
8024 newsrv->minconn = newsrv->maxconn;
8025 }
8026
Emeric Brun01f8e2f2012-05-18 16:02:00 +02008027#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02008028 if (newsrv->use_ssl || newsrv->check.use_ssl)
8029 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02008030#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02008031
Willy Tarreau2f075e92013-12-03 11:11:34 +01008032 /* set the check type on the server */
8033 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
8034
Willy Tarreau62c3be22012-01-20 13:12:32 +01008035 if (newsrv->trackit) {
8036 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02008037 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008038 char *pname, *sname;
8039
8040 pname = newsrv->trackit;
8041 sname = strrchr(pname, '/');
8042
8043 if (sname)
8044 *sname++ = '\0';
8045 else {
8046 sname = pname;
8047 pname = NULL;
8048 }
8049
8050 if (pname) {
Willy Tarreau9e0bb102015-05-26 11:24:42 +02008051 px = proxy_be_by_name(pname);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008052 if (!px) {
8053 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
8054 proxy_type_str(curproxy), curproxy->id,
8055 newsrv->id, pname);
8056 cfgerr++;
8057 goto next_srv;
8058 }
8059 } else
8060 px = curproxy;
8061
8062 srv = findserver(px, sname);
8063 if (!srv) {
8064 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
8065 proxy_type_str(curproxy), curproxy->id,
8066 newsrv->id, sname);
8067 cfgerr++;
8068 goto next_srv;
8069 }
8070
Willy Tarreau32091232014-05-16 13:52:00 +02008071 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
8072 !(srv->agent.state & CHK_ST_CONFIGURED) &&
8073 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01008074 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02008075 "tracking as it does not have any check nor agent enabled.\n",
8076 proxy_type_str(curproxy), curproxy->id,
8077 newsrv->id, px->id, srv->id);
8078 cfgerr++;
8079 goto next_srv;
8080 }
8081
8082 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
8083
8084 if (loop) {
8085 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
8086 "belongs to a tracking chain looping back to %s/%s.\n",
8087 proxy_type_str(curproxy), curproxy->id,
8088 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008089 cfgerr++;
8090 goto next_srv;
8091 }
8092
8093 if (curproxy != px &&
8094 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
8095 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
8096 "tracking: disable-on-404 option inconsistency.\n",
8097 proxy_type_str(curproxy), curproxy->id,
8098 newsrv->id, px->id, srv->id);
8099 cfgerr++;
8100 goto next_srv;
8101 }
8102
8103 /* if the other server is forced disabled, we have to do the same here */
Willy Tarreau20125212014-05-13 19:44:56 +02008104 if (srv->admin & SRV_ADMF_MAINT) {
Willy Tarreaua0066dd2014-05-16 11:25:16 +02008105 newsrv->admin |= SRV_ADMF_IMAINT;
Willy Tarreau892337c2014-05-13 23:41:20 +02008106 newsrv->state = SRV_ST_STOPPED;
Simon Horman125d0992013-02-24 17:23:38 +09008107 newsrv->check.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008108 }
8109
8110 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01008111 newsrv->tracknext = srv->trackers;
8112 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008113
8114 free(newsrv->trackit);
8115 newsrv->trackit = NULL;
8116 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008117
8118 /*
8119 * resolve server's resolvers name and update the resolvers pointer
8120 * accordingly
8121 */
8122 if (newsrv->resolvers_id) {
8123 struct dns_resolvers *curr_resolvers;
8124 int found;
8125
8126 found = 0;
8127 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
8128 if (!strcmp(curr_resolvers->id, newsrv->resolvers_id)) {
8129 found = 1;
8130 break;
8131 }
8132 }
8133
8134 if (!found) {
8135 Alert("config : %s '%s', server '%s': unable to find required resolvers '%s'\n",
8136 proxy_type_str(curproxy), curproxy->id,
8137 newsrv->id, newsrv->resolvers_id);
8138 cfgerr++;
8139 } else {
8140 free(newsrv->resolvers_id);
8141 newsrv->resolvers_id = NULL;
8142 if (newsrv->resolution)
8143 newsrv->resolution->resolvers = curr_resolvers;
8144 }
8145 }
8146 else {
8147 /* if no resolvers section associated to this server
8148 * we can clean up the associated resolution structure
8149 */
8150 if (newsrv->resolution) {
8151 free(newsrv->resolution->hostname_dn);
8152 newsrv->resolution->hostname_dn = NULL;
8153 free(newsrv->resolution);
8154 newsrv->resolution = NULL;
8155 }
8156 }
8157
Willy Tarreau62c3be22012-01-20 13:12:32 +01008158 next_srv:
8159 newsrv = newsrv->next;
8160 }
8161
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008162 /* We have to initialize the server lookup mechanism depending
8163 * on what LB algorithm was choosen.
8164 */
8165
8166 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
8167 switch (curproxy->lbprm.algo & BE_LB_KIND) {
8168 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02008169 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
8170 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8171 init_server_map(curproxy);
8172 } else {
8173 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
8174 fwrr_init_server_groups(curproxy);
8175 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008176 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008177
Willy Tarreau3ebb1162012-02-13 16:57:44 +01008178 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01008179 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
8180 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
8181 fwlc_init_server_tree(curproxy);
8182 } else {
8183 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
8184 fas_init_server_tree(curproxy);
8185 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008186 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008187
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008188 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008189 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
8190 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
8191 chash_init_server_tree(curproxy);
8192 } else {
8193 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8194 init_server_map(curproxy);
8195 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008196 break;
8197 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02008198
8199 if (curproxy->options & PR_O_LOGASAP)
8200 curproxy->to_log &= ~LW_BYTES;
8201
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008202 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01008203 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008204 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
8205 proxy_type_str(curproxy), curproxy->id);
8206 err_code |= ERR_WARN;
8207 }
8208
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008209 if (curproxy->mode != PR_MODE_HTTP) {
8210 int optnum;
8211
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008212 if (curproxy->uri_auth) {
8213 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
8214 proxy_type_str(curproxy), curproxy->id);
8215 err_code |= ERR_WARN;
8216 curproxy->uri_auth = NULL;
8217 }
8218
Willy Tarreau87cf5142011-08-19 22:57:24 +02008219 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008220 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8221 "forwardfor", proxy_type_str(curproxy), curproxy->id);
8222 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02008223 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008224 }
8225
8226 if (curproxy->options & PR_O_ORGTO) {
8227 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8228 "originalto", proxy_type_str(curproxy), curproxy->id);
8229 err_code |= ERR_WARN;
8230 curproxy->options &= ~PR_O_ORGTO;
8231 }
8232
8233 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
8234 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
8235 (curproxy->cap & cfg_opts[optnum].cap) &&
8236 (curproxy->options & cfg_opts[optnum].val)) {
8237 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8238 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
8239 err_code |= ERR_WARN;
8240 curproxy->options &= ~cfg_opts[optnum].val;
8241 }
8242 }
8243
8244 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
8245 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
8246 (curproxy->cap & cfg_opts2[optnum].cap) &&
8247 (curproxy->options2 & cfg_opts2[optnum].val)) {
8248 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8249 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
8250 err_code |= ERR_WARN;
8251 curproxy->options2 &= ~cfg_opts2[optnum].val;
8252 }
8253 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008254
Willy Tarreau29fbe512015-08-20 19:35:14 +02008255#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008256 if (curproxy->conn_src.bind_hdr_occ) {
8257 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008258 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01008259 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008260 err_code |= ERR_WARN;
8261 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008262#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008263 }
8264
Willy Tarreaubaaee002006-06-26 02:48:02 +02008265 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01008266 * ensure that we're not cross-dressing a TCP server into HTTP.
8267 */
8268 newsrv = curproxy->srv;
8269 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01008270 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008271 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
8272 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008273 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01008274 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008275
Willy Tarreau0cec3312011-10-31 13:49:26 +01008276 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
8277 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
8278 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8279 err_code |= ERR_WARN;
8280 }
8281
Willy Tarreauc93cd162014-05-13 15:54:22 +02008282 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02008283 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
8284 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8285 err_code |= ERR_WARN;
8286 }
8287
Willy Tarreau29fbe512015-08-20 19:35:14 +02008288#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008289 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
8290 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008291 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 +01008292 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008293 err_code |= ERR_WARN;
8294 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008295#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01008296 newsrv = newsrv->next;
8297 }
8298
Willy Tarreaue42bd962014-09-16 16:21:19 +02008299 /* check if we have a frontend with "tcp-request content" looking at L7
8300 * with no inspect-delay
8301 */
8302 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
8303 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008304 if (trule->action == ACT_TCP_CAPTURE &&
Thierry FOURNIERd0d65ae2015-08-04 08:21:12 +02008305 !(trule->arg.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008306 break;
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008307 if ((trule->action >= ACT_ACTION_TRK_SC0 && trule->action <= ACT_ACTION_TRK_SCMAX) &&
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008308 !(trule->arg.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008309 break;
8310 }
8311
8312 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
8313 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
8314 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
8315 " This means that these rules will randomly find their contents. This can be fixed by"
8316 " setting the tcp-request inspect-delay.\n",
8317 proxy_type_str(curproxy), curproxy->id);
8318 err_code |= ERR_WARN;
8319 }
8320 }
8321
Willy Tarreauc1a21672009-08-16 22:37:44 +02008322 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02008323 if (!curproxy->accept)
8324 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02008325
Willy Tarreauc1a21672009-08-16 22:37:44 +02008326 if (curproxy->tcp_req.inspect_delay ||
8327 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02008328 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008329
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008330 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008331 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008332 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008333 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008334
8335 /* both TCP and HTTP must check switching rules */
8336 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
8337 }
8338
8339 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02008340 if (curproxy->tcp_req.inspect_delay ||
8341 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
8342 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
8343
Emeric Brun97679e72010-09-23 17:56:44 +02008344 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
8345 curproxy->be_rsp_ana |= AN_RES_INSPECT;
8346
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008347 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008348 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008349 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008350 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008351
8352 /* If the backend does requires RDP cookie persistence, we have to
8353 * enable the corresponding analyser.
8354 */
8355 if (curproxy->options2 & PR_O2_RDPC_PRST)
8356 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
8357 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008358 }
8359
8360 /***********************************************************/
8361 /* At this point, target names have already been resolved. */
8362 /***********************************************************/
8363
8364 /* Check multi-process mode compatibility */
8365
8366 if (global.nbproc > 1 && global.stats_fe) {
8367 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8368 unsigned long mask;
8369
8370 mask = nbits(global.nbproc);
8371 if (global.stats_fe->bind_proc)
8372 mask &= global.stats_fe->bind_proc;
8373
8374 if (bind_conf->bind_proc)
8375 mask &= bind_conf->bind_proc;
8376
8377 /* stop here if more than one process is used */
David Carliere6c39412015-07-02 07:00:17 +00008378 if (my_popcountl(mask) > 1)
Willy Tarreau419ead82014-09-16 13:41:21 +02008379 break;
8380 }
8381 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
8382 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");
8383 }
8384 }
8385
8386 /* Make each frontend inherit bind-process from its listeners when not specified. */
8387 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8388 if (curproxy->bind_proc)
8389 continue;
8390
8391 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8392 unsigned long mask;
8393
Willy Tarreaue428b082015-05-04 21:57:58 +02008394 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008395 curproxy->bind_proc |= mask;
8396 }
8397
8398 if (!curproxy->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008399 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008400 }
8401
8402 if (global.stats_fe) {
8403 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8404 unsigned long mask;
8405
Willy Tarreaue428b082015-05-04 21:57:58 +02008406 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008407 global.stats_fe->bind_proc |= mask;
8408 }
8409 if (!global.stats_fe->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008410 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008411 }
8412
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02008413 /* propagate bindings from frontends to backends. Don't do it if there
8414 * are any fatal errors as we must not call it with unresolved proxies.
8415 */
8416 if (!cfgerr) {
8417 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8418 if (curproxy->cap & PR_CAP_FE)
8419 propagate_processes(curproxy, NULL);
8420 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008421 }
8422
8423 /* Bind each unbound backend to all processes when not specified. */
8424 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8425 if (curproxy->bind_proc)
8426 continue;
Willy Tarreaue428b082015-05-04 21:57:58 +02008427 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008428 }
8429
8430 /*******************************************************/
8431 /* At this step, all proxies have a non-null bind_proc */
8432 /*******************************************************/
8433
8434 /* perform the final checks before creating tasks */
8435
8436 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8437 struct listener *listener;
8438 unsigned int next_id;
8439 int nbproc;
8440
David Carliere6c39412015-07-02 07:00:17 +00008441 nbproc = my_popcountl(curproxy->bind_proc & nbits(global.nbproc));
Willy Tarreauc1a21672009-08-16 22:37:44 +02008442
Emeric Brunc52962f2012-11-15 18:28:02 +01008443#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008444 /* Configure SSL for each bind line.
8445 * Note: if configuration fails at some point, the ->ctx member
8446 * remains NULL so that listeners can later detach.
8447 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008448 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008449 int alloc_ctx;
8450
Emeric Brunc52962f2012-11-15 18:28:02 +01008451 if (!bind_conf->is_ssl) {
8452 if (bind_conf->default_ctx) {
8453 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
8454 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
8455 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008456 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01008457 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008458 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02008459 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008460 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008461 cfgerr++;
8462 continue;
8463 }
8464
Emeric Brun8dc60392014-05-09 13:52:00 +02008465 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008466 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02008467 if (alloc_ctx == SHCTX_E_INIT_LOCK)
8468 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");
8469 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008470 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02008471 cfgerr++;
8472 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008473 }
8474
Emeric Brunfc0421f2012-09-07 17:30:07 +02008475 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008476 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008477
8478 /* initialize CA variables if the certificates generation is enabled */
8479 cfgerr += ssl_sock_load_ca(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008480 }
Emeric Brunc52962f2012-11-15 18:28:02 +01008481#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008482
Willy Tarreaue6b98942007-10-29 01:09:36 +01008483 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008484 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008485 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008486 if (!listener->luid) {
8487 /* listener ID not set, use automatic numbering with first
8488 * spare entry starting with next_luid.
8489 */
8490 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
8491 listener->conf.id.key = listener->luid = next_id;
8492 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008493 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01008494 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008495
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008496 /* enable separate counters */
8497 if (curproxy->options2 & PR_O2_SOCKSTAT) {
8498 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01008499 if (!listener->name)
8500 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008501 }
Willy Tarreau81796be2012-09-22 19:11:47 +02008502
Willy Tarreaue6b98942007-10-29 01:09:36 +01008503 if (curproxy->options & PR_O_TCP_NOLING)
8504 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02008505 if (!listener->maxconn)
8506 listener->maxconn = curproxy->maxconn;
8507 if (!listener->backlog)
8508 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01008509 if (!listener->maxaccept)
8510 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
8511
8512 /* we want to have an optimal behaviour on single process mode to
8513 * maximize the work at once, but in multi-process we want to keep
8514 * some fairness between processes, so we target half of the max
8515 * number of events to be balanced over all the processes the proxy
8516 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
8517 * used to disable the limit.
8518 */
8519 if (listener->maxaccept > 0) {
8520 if (nbproc > 1)
8521 listener->maxaccept = (listener->maxaccept + 1) / 2;
8522 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
8523 }
8524
Willy Tarreau9903f0e2015-04-04 18:50:31 +02008525 listener->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02008526 listener->handler = process_stream;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008527 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01008528 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01008529
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008530 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
8531 listener->options |= LI_O_TCP_RULES;
8532
Willy Tarreaude3041d2010-05-31 10:56:17 +02008533 if (curproxy->mon_mask.s_addr)
8534 listener->options |= LI_O_CHK_MONNET;
8535
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008536 /* smart accept mode is automatic in HTTP mode */
8537 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008538 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008539 !(curproxy->no_options2 & PR_O2_SMARTACC)))
8540 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01008541 }
8542
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008543 /* Release unused SSL configs */
8544 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8545 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008546 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008547#ifdef USE_OPENSSL
Christopher Faulet31af49d2015-06-09 17:29:50 +02008548 ssl_sock_free_ca(bind_conf);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008549 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008550 free(bind_conf->ca_file);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008551 free(bind_conf->ca_sign_file);
8552 free(bind_conf->ca_sign_pass);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008553 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02008554 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008555 free(bind_conf->crl_file);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008556 if(bind_conf->keys_ref) {
8557 free(bind_conf->keys_ref->filename);
8558 free(bind_conf->keys_ref->tlskeys);
8559 free(bind_conf->keys_ref);
8560 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008561#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008562 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008563
Willy Tarreau102df612014-05-07 23:56:38 +02008564 if (nbproc > 1) {
8565 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02008566 int count, maxproc = 0;
8567
8568 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
David Carliere6c39412015-07-02 07:00:17 +00008569 count = my_popcountl(bind_conf->bind_proc);
Willy Tarreaueb791e02014-09-16 15:11:04 +02008570 if (count > maxproc)
8571 maxproc = count;
8572 }
8573 /* backends have 0, frontends have 1 or more */
8574 if (maxproc != 1)
8575 Warning("Proxy '%s': in multi-process mode, stats will be"
8576 " limited to process assigned to the current request.\n",
8577 curproxy->id);
8578
Willy Tarreau102df612014-05-07 23:56:38 +02008579 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
8580 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
8581 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008582 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008583 }
Willy Tarreau102df612014-05-07 23:56:38 +02008584 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
8585 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
8586 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008587 }
8588 }
Willy Tarreau918ff602011-07-25 16:33:49 +02008589
8590 /* create the task associated with the proxy */
8591 curproxy->task = task_new();
8592 if (curproxy->task) {
8593 curproxy->task->context = curproxy;
8594 curproxy->task->process = manage_proxy;
8595 /* no need to queue, it will be done automatically if some
8596 * listener gets limited.
8597 */
8598 curproxy->task->expire = TICK_ETERNITY;
8599 } else {
8600 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
8601 curproxy->id);
8602 cfgerr++;
8603 }
Willy Tarreaub369a042014-09-16 13:21:03 +02008604 }
8605
Willy Tarreaufbb78422011-06-05 15:38:35 +02008606 /* automatically compute fullconn if not set. We must not do it in the
8607 * loop above because cross-references are not yet fully resolved.
8608 */
8609 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8610 /* If <fullconn> is not set, let's set it to 10% of the sum of
8611 * the possible incoming frontend's maxconns.
8612 */
8613 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
8614 struct proxy *fe;
8615 int total = 0;
8616
8617 /* sum up the number of maxconns of frontends which
8618 * reference this backend at least once or which are
8619 * the same one ('listen').
8620 */
8621 for (fe = proxy; fe; fe = fe->next) {
8622 struct switching_rule *rule;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008623 int found = 0;
8624
8625 if (!(fe->cap & PR_CAP_FE))
8626 continue;
8627
8628 if (fe == curproxy) /* we're on a "listen" instance */
8629 found = 1;
8630
8631 if (fe->defbe.be == curproxy) /* "default_backend" */
8632 found = 1;
8633
8634 /* check if a "use_backend" rule matches */
8635 if (!found) {
8636 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01008637 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02008638 found = 1;
8639 break;
8640 }
8641 }
8642 }
8643
Willy Tarreaufbb78422011-06-05 15:38:35 +02008644 /* now we've checked all possible ways to reference a backend
8645 * from a frontend.
8646 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02008647 if (!found)
8648 continue;
8649 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008650 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02008651 /* we have the sum of the maxconns in <total>. We only
8652 * keep 10% of that sum to set the default fullconn, with
8653 * a hard minimum of 1 (to avoid a divide by zero).
8654 */
8655 curproxy->fullconn = (total + 9) / 10;
8656 if (!curproxy->fullconn)
8657 curproxy->fullconn = 1;
8658 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01008659 }
8660
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008661 /*
8662 * Recount currently required checks.
8663 */
8664
8665 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
8666 int optnum;
8667
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008668 for (optnum = 0; cfg_opts[optnum].name; optnum++)
8669 if (curproxy->options & cfg_opts[optnum].val)
8670 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008671
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008672 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
8673 if (curproxy->options2 & cfg_opts2[optnum].val)
8674 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008675 }
8676
Willy Tarreau0fca4832015-05-01 19:12:05 +02008677 /* compute the required process bindings for the peers */
8678 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
8679 if (curproxy->table.peers.p)
8680 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
8681
Willy Tarreau122541c2011-09-07 21:24:49 +02008682 if (peers) {
8683 struct peers *curpeers = peers, **last;
8684 struct peer *p, *pb;
8685
Willy Tarreau1e273012015-05-01 19:15:17 +02008686 /* Remove all peers sections which don't have a valid listener,
8687 * which are not used by any table, or which are bound to more
8688 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02008689 */
8690 last = &peers;
8691 while (*last) {
8692 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008693
8694 if (curpeers->state == PR_STSTOPPED) {
8695 /* the "disabled" keyword was present */
8696 if (curpeers->peers_fe)
8697 stop_proxy(curpeers->peers_fe);
8698 curpeers->peers_fe = NULL;
8699 }
8700 else if (!curpeers->peers_fe) {
8701 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
8702 curpeers->id, localpeer);
8703 }
David Carliere6c39412015-07-02 07:00:17 +00008704 else if (my_popcountl(curpeers->peers_fe->bind_proc) != 1) {
Willy Tarreau1e273012015-05-01 19:15:17 +02008705 /* either it's totally stopped or too much used */
8706 if (curpeers->peers_fe->bind_proc) {
8707 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreau64c57222015-05-04 21:48:51 +02008708 "running in different processes (%d different ones). "
8709 "Check global.nbproc and all tables' bind-process "
David Carliere6c39412015-07-02 07:00:17 +00008710 "settings.\n", curpeers->id, my_popcountl(curpeers->peers_fe->bind_proc));
Willy Tarreau1e273012015-05-01 19:15:17 +02008711 cfgerr++;
8712 }
8713 stop_proxy(curpeers->peers_fe);
8714 curpeers->peers_fe = NULL;
8715 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008716 else {
Emeric Brunb3971ab2015-05-12 18:49:09 +02008717 peers_init_sync(curpeers);
Willy Tarreau122541c2011-09-07 21:24:49 +02008718 last = &curpeers->next;
8719 continue;
8720 }
8721
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008722 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02008723 p = curpeers->remote;
8724 while (p) {
8725 pb = p->next;
8726 free(p->id);
8727 free(p);
8728 p = pb;
8729 }
8730
8731 /* Destroy and unlink this curpeers section.
8732 * Note: curpeers is backed up into *last.
8733 */
8734 free(curpeers->id);
8735 curpeers = curpeers->next;
8736 free(*last);
8737 *last = curpeers;
8738 }
8739 }
8740
Willy Tarreau6866f3f2015-05-01 19:09:08 +02008741 /* initialize stick-tables on backend capable proxies. This must not
8742 * be done earlier because the data size may be discovered while parsing
8743 * other proxies.
8744 */
8745 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8746 if (curproxy->state == PR_STSTOPPED)
8747 continue;
8748
8749 if (!stktable_init(&curproxy->table)) {
8750 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
8751 cfgerr++;
8752 }
8753 }
8754
Simon Horman0d16a402015-01-30 11:22:58 +09008755 if (mailers) {
8756 struct mailers *curmailers = mailers, **last;
8757 struct mailer *m, *mb;
8758
8759 /* Remove all mailers sections which don't have a valid listener.
8760 * This can happen when a mailers section is never referenced.
8761 */
8762 last = &mailers;
8763 while (*last) {
8764 curmailers = *last;
8765 if (curmailers->users) {
8766 last = &curmailers->next;
8767 continue;
8768 }
8769
8770 Warning("Removing incomplete section 'mailers %s'.\n",
8771 curmailers->id);
8772
8773 m = curmailers->mailer_list;
8774 while (m) {
8775 mb = m->next;
8776 free(m->id);
8777 free(m);
8778 m = mb;
8779 }
8780
8781 /* Destroy and unlink this curmailers section.
8782 * Note: curmailers is backed up into *last.
8783 */
8784 free(curmailers->id);
8785 curmailers = curmailers->next;
8786 free(*last);
8787 *last = curmailers;
8788 }
8789 }
8790
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02008791 /* Update server_state_file_name to backend name if backend is supposed to use
8792 * a server-state file locally defined and none has been provided */
8793 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8794 if (curproxy->load_server_state_from_file == PR_SRV_STATE_FILE_LOCAL &&
8795 curproxy->server_state_file_name == NULL)
8796 curproxy->server_state_file_name = strdup(curproxy->id);
8797 }
8798
Willy Tarreau34eb6712011-10-24 18:15:04 +02008799 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02008800 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02008801 MEM_F_SHARED);
8802
Willy Tarreaubb925012009-07-23 13:36:36 +02008803 if (cfgerr > 0)
8804 err_code |= ERR_ALERT | ERR_FATAL;
8805 out:
8806 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02008807}
8808
Willy Tarreau5b2c3362008-07-09 19:39:06 +02008809/*
8810 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
8811 * parsing sessions.
8812 */
8813void cfg_register_keywords(struct cfg_kw_list *kwl)
8814{
8815 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
8816}
Willy Tarreaubaaee002006-06-26 02:48:02 +02008817
Willy Tarreau5b2c3362008-07-09 19:39:06 +02008818/*
8819 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
8820 */
8821void cfg_unregister_keywords(struct cfg_kw_list *kwl)
8822{
8823 LIST_DEL(&kwl->list);
8824 LIST_INIT(&kwl->list);
8825}
Willy Tarreaubaaee002006-06-26 02:48:02 +02008826
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01008827/* this function register new section in the haproxy configuration file.
8828 * <section_name> is the name of this new section and <section_parser>
8829 * is the called parser. If two section declaration have the same name,
8830 * only the first declared is used.
8831 */
8832int cfg_register_section(char *section_name,
8833 int (*section_parser)(const char *, int, char **, int))
8834{
8835 struct cfg_section *cs;
8836
8837 cs = calloc(1, sizeof(*cs));
8838 if (!cs) {
8839 Alert("register section '%s': out of memory.\n", section_name);
8840 return 0;
8841 }
8842
8843 cs->section_name = section_name;
8844 cs->section_parser = section_parser;
8845
8846 LIST_ADDQ(&sections, &cs->list);
8847
8848 return 1;
8849}
8850
Willy Tarreaubaaee002006-06-26 02:48:02 +02008851/*
David Carlier845efb52015-09-25 11:49:18 +01008852 * free all config section entries
8853 */
8854void cfg_unregister_sections(void)
8855{
8856 struct cfg_section *cs, *ics;
8857
8858 list_for_each_entry_safe(cs, ics, &sections, list) {
8859 LIST_DEL(&cs->list);
8860 free(cs);
8861 }
8862}
8863
8864/*
Willy Tarreaubaaee002006-06-26 02:48:02 +02008865 * Local variables:
8866 * c-indent-level: 8
8867 * c-basic-offset: 8
8868 * End:
8869 */