blob: 3b7b390858491dc66f8b881fc689801aa5c17e3d [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,
243 NULL);
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]);
831 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
832 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100833 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100834 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200835 }
836 else if (!strcmp(args[0], "tune.maxrewrite")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200837 if (alertif_too_many_args(1, file, linenum, args, &err_code))
838 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200839 if (*(args[1]) == 0) {
840 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
841 err_code |= ERR_ALERT | ERR_FATAL;
842 goto out;
843 }
844 global.tune.maxrewrite = atol(args[1]);
845 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
846 global.tune.maxrewrite = global.tune.bufsize / 2;
847 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100848 else if (!strcmp(args[0], "tune.idletimer")) {
849 unsigned int idle;
850 const char *res;
851
William Lallemand1a748ae2015-05-19 16:37:23 +0200852 if (alertif_too_many_args(1, file, linenum, args, &err_code))
853 goto out;
Willy Tarreau7e312732014-02-12 16:35:14 +0100854 if (*(args[1]) == 0) {
855 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
856 err_code |= ERR_ALERT | ERR_FATAL;
857 goto out;
858 }
859
860 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
861 if (res) {
862 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
863 file, linenum, *res, args[0]);
864 err_code |= ERR_ALERT | ERR_FATAL;
865 goto out;
866 }
867
868 if (idle > 65535) {
869 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
870 err_code |= ERR_ALERT | ERR_FATAL;
871 goto out;
872 }
873 global.tune.idle_timer = idle;
874 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100875 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200876 if (alertif_too_many_args(1, file, linenum, args, &err_code))
877 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100878 if (global.tune.client_rcvbuf != 0) {
879 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
880 err_code |= ERR_ALERT;
881 goto out;
882 }
883 if (*(args[1]) == 0) {
884 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
885 err_code |= ERR_ALERT | ERR_FATAL;
886 goto out;
887 }
888 global.tune.client_rcvbuf = atol(args[1]);
889 }
890 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200891 if (alertif_too_many_args(1, file, linenum, args, &err_code))
892 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100893 if (global.tune.server_rcvbuf != 0) {
894 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
895 err_code |= ERR_ALERT;
896 goto out;
897 }
898 if (*(args[1]) == 0) {
899 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
900 err_code |= ERR_ALERT | ERR_FATAL;
901 goto out;
902 }
903 global.tune.server_rcvbuf = atol(args[1]);
904 }
905 else if (!strcmp(args[0], "tune.sndbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200906 if (alertif_too_many_args(1, file, linenum, args, &err_code))
907 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100908 if (global.tune.client_sndbuf != 0) {
909 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
910 err_code |= ERR_ALERT;
911 goto out;
912 }
913 if (*(args[1]) == 0) {
914 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
915 err_code |= ERR_ALERT | ERR_FATAL;
916 goto out;
917 }
918 global.tune.client_sndbuf = atol(args[1]);
919 }
920 else if (!strcmp(args[0], "tune.sndbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200921 if (alertif_too_many_args(1, file, linenum, args, &err_code))
922 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100923 if (global.tune.server_sndbuf != 0) {
924 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
925 err_code |= ERR_ALERT;
926 goto out;
927 }
928 if (*(args[1]) == 0) {
929 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
930 err_code |= ERR_ALERT | ERR_FATAL;
931 goto out;
932 }
933 global.tune.server_sndbuf = atol(args[1]);
934 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200935 else if (!strcmp(args[0], "tune.pipesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200936 if (alertif_too_many_args(1, file, linenum, args, &err_code))
937 goto out;
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200938 if (*(args[1]) == 0) {
939 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
940 err_code |= ERR_ALERT | ERR_FATAL;
941 goto out;
942 }
943 global.tune.pipesize = atol(args[1]);
944 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100945 else if (!strcmp(args[0], "tune.http.cookielen")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200946 if (alertif_too_many_args(1, file, linenum, args, &err_code))
947 goto out;
Willy Tarreau193b8c62012-11-22 00:17:38 +0100948 if (*(args[1]) == 0) {
949 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
950 err_code |= ERR_ALERT | ERR_FATAL;
951 goto out;
952 }
953 global.tune.cookie_len = atol(args[1]) + 1;
954 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200955 else if (!strcmp(args[0], "tune.http.maxhdr")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200956 if (alertif_too_many_args(1, file, linenum, args, &err_code))
957 goto out;
Willy Tarreauac1932d2011-10-24 19:14:41 +0200958 if (*(args[1]) == 0) {
959 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
960 err_code |= ERR_ALERT | ERR_FATAL;
961 goto out;
962 }
963 global.tune.max_http_hdr = atol(args[1]);
964 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100965 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
966#ifdef USE_ZLIB
William Lallemand1a748ae2015-05-19 16:37:23 +0200967 if (alertif_too_many_args(1, file, linenum, args, &err_code))
968 goto out;
William Lallemanda509e4c2012-11-07 16:54:34 +0100969 if (*args[1]) {
970 global.tune.zlibmemlevel = atoi(args[1]);
971 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
972 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
973 file, linenum, args[0]);
974 err_code |= ERR_ALERT | ERR_FATAL;
975 goto out;
976 }
977 } else {
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' is not implemented.\n", file, linenum, args[0]);
985 err_code |= ERR_ALERT | ERR_FATAL;
986 goto out;
987#endif
988 }
989 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
990#ifdef USE_ZLIB
William Lallemand1a748ae2015-05-19 16:37:23 +0200991 if (alertif_too_many_args(1, file, linenum, args, &err_code))
992 goto out;
William Lallemanda509e4c2012-11-07 16:54:34 +0100993 if (*args[1]) {
994 global.tune.zlibwindowsize = atoi(args[1]);
995 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
996 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
997 file, linenum, args[0]);
998 err_code |= ERR_ALERT | ERR_FATAL;
999 goto out;
1000 }
1001 } else {
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' is not implemented.\n", file, linenum, args[0]);
1009 err_code |= ERR_ALERT | ERR_FATAL;
1010 goto out;
1011#endif
1012 }
William Lallemandf3747832012-11-09 12:33:10 +01001013 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001014 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1015 goto out;
William Lallemandf3747832012-11-09 12:33:10 +01001016 if (*args[1]) {
1017 global.tune.comp_maxlevel = atoi(args[1]);
1018 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
1019 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1020 file, linenum, args[0]);
1021 err_code |= ERR_ALERT | ERR_FATAL;
1022 goto out;
1023 }
1024 } else {
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 }
Willy Tarreauf3045d22015-04-29 16:24:50 +02001031 else if (!strcmp(args[0], "tune.pattern.cache-size")) {
1032 if (*args[1]) {
1033 global.tune.pattern_cache = atoi(args[1]);
1034 if (global.tune.pattern_cache < 0) {
1035 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
1036 file, linenum, args[0]);
1037 err_code |= ERR_ALERT | ERR_FATAL;
1038 goto out;
1039 }
1040 } else {
1041 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
1042 file, linenum, args[0]);
1043 err_code |= ERR_ALERT | ERR_FATAL;
1044 goto out;
1045 }
1046 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001047 else if (!strcmp(args[0], "uid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001048 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1049 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001050 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001051 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001052 err_code |= ERR_ALERT;
1053 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001054 }
1055 if (*(args[1]) == 0) {
1056 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001057 err_code |= ERR_ALERT | ERR_FATAL;
1058 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001059 }
1060 global.uid = atol(args[1]);
1061 }
1062 else if (!strcmp(args[0], "gid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001063 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1064 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001065 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001066 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001067 err_code |= ERR_ALERT;
1068 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001069 }
1070 if (*(args[1]) == 0) {
1071 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001072 err_code |= ERR_ALERT | ERR_FATAL;
1073 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001074 }
1075 global.gid = atol(args[1]);
1076 }
Simon Horman98637e52014-06-20 12:30:16 +09001077 else if (!strcmp(args[0], "external-check")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001078 if (alertif_too_many_args(0, file, linenum, args, &err_code))
1079 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09001080 global.external_check = 1;
1081 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001082 /* user/group name handling */
1083 else if (!strcmp(args[0], "user")) {
1084 struct passwd *ha_user;
William Lallemand1a748ae2015-05-19 16:37:23 +02001085 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1086 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001087 if (global.uid != 0) {
1088 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001089 err_code |= ERR_ALERT;
1090 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001091 }
1092 errno = 0;
1093 ha_user = getpwnam(args[1]);
1094 if (ha_user != NULL) {
1095 global.uid = (int)ha_user->pw_uid;
1096 }
1097 else {
1098 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 +02001099 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001100 }
1101 }
1102 else if (!strcmp(args[0], "group")) {
1103 struct group *ha_group;
William Lallemand1a748ae2015-05-19 16:37:23 +02001104 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1105 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001106 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02001107 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001108 err_code |= ERR_ALERT;
1109 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001110 }
1111 errno = 0;
1112 ha_group = getgrnam(args[1]);
1113 if (ha_group != NULL) {
1114 global.gid = (int)ha_group->gr_gid;
1115 }
1116 else {
1117 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 +02001118 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001119 }
1120 }
1121 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +02001122 else if (!strcmp(args[0], "nbproc")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001123 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1124 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001125 if (*(args[1]) == 0) {
1126 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001127 err_code |= ERR_ALERT | ERR_FATAL;
1128 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001129 }
1130 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001131 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
1132 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
1133 file, linenum, args[0], LONGBITS, global.nbproc);
1134 err_code |= ERR_ALERT | ERR_FATAL;
1135 goto out;
1136 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001137 }
1138 else if (!strcmp(args[0], "maxconn")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001139 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1140 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001141 if (global.maxconn != 0) {
1142 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001143 err_code |= ERR_ALERT;
1144 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001145 }
1146 if (*(args[1]) == 0) {
1147 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001148 err_code |= ERR_ALERT | ERR_FATAL;
1149 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001150 }
1151 global.maxconn = atol(args[1]);
1152#ifdef SYSTEM_MAXCONN
1153 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
1154 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);
1155 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +02001156 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001157 }
1158#endif /* SYSTEM_MAXCONN */
1159 }
Willy Tarreau403edff2012-09-06 11:58:37 +02001160 else if (!strcmp(args[0], "maxsslconn")) {
1161#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001162 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1163 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001164 if (*(args[1]) == 0) {
1165 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1166 err_code |= ERR_ALERT | ERR_FATAL;
1167 goto out;
1168 }
1169 global.maxsslconn = atol(args[1]);
1170#else
Emeric Brun0914df82012-10-02 18:45:42 +02001171 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1172 err_code |= ERR_ALERT | ERR_FATAL;
1173 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001174#endif
1175 }
Willy Tarreau610f04b2014-02-13 11:36:41 +01001176 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
1177#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001178 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1179 goto out;
Willy Tarreau610f04b2014-02-13 11:36:41 +01001180 if (*(args[1]) == 0) {
1181 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1182 err_code |= ERR_ALERT | ERR_FATAL;
1183 goto out;
1184 }
1185 free(global.listen_default_ciphers);
1186 global.listen_default_ciphers = strdup(args[1]);
1187#else
1188 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1189 err_code |= ERR_ALERT | ERR_FATAL;
1190 goto out;
1191#endif
1192 }
1193 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
1194#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001195 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1196 goto out;
Willy Tarreau610f04b2014-02-13 11:36:41 +01001197 if (*(args[1]) == 0) {
1198 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1199 err_code |= ERR_ALERT | ERR_FATAL;
1200 goto out;
1201 }
1202 free(global.connect_default_ciphers);
1203 global.connect_default_ciphers = strdup(args[1]);
1204#else
1205 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1206 err_code |= ERR_ALERT | ERR_FATAL;
1207 goto out;
1208#endif
1209 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02001210#ifdef USE_OPENSSL
1211#ifndef OPENSSL_NO_DH
1212 else if (!strcmp(args[0], "ssl-dh-param-file")) {
1213 if (*(args[1]) == 0) {
1214 Alert("parsing [%s:%d] : '%s' expects a file path as an argument.\n", file, linenum, args[0]);
1215 err_code |= ERR_ALERT | ERR_FATAL;
1216 goto out;
1217 }
1218 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
1219 Alert("parsing [%s:%d] : '%s': unable to load DH parameters from file <%s>.\n", file, linenum, args[0], args[1]);
1220 err_code |= ERR_ALERT | ERR_FATAL;
1221 goto out;
1222 }
1223 }
1224#endif
1225#endif
Emeric Brun850efd52014-01-29 12:24:34 +01001226 else if (!strcmp(args[0], "ssl-server-verify")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001227 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1228 goto out;
Emeric Brun850efd52014-01-29 12:24:34 +01001229 if (*(args[1]) == 0) {
1230 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1231 err_code |= ERR_ALERT | ERR_FATAL;
1232 goto out;
1233 }
1234 if (strcmp(args[1],"none") == 0)
1235 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1236 else if (strcmp(args[1],"required") == 0)
1237 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1238 else {
1239 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1240 err_code |= ERR_ALERT | ERR_FATAL;
1241 goto out;
1242 }
1243 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001244 else if (!strcmp(args[0], "maxconnrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001245 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1246 goto out;
Willy Tarreau81c25d02011-09-07 15:17:21 +02001247 if (global.cps_lim != 0) {
1248 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1249 err_code |= ERR_ALERT;
1250 goto out;
1251 }
1252 if (*(args[1]) == 0) {
1253 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1254 err_code |= ERR_ALERT | ERR_FATAL;
1255 goto out;
1256 }
1257 global.cps_lim = atol(args[1]);
1258 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001259 else if (!strcmp(args[0], "maxsessrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001260 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1261 goto out;
Willy Tarreau93e7c002013-10-07 18:51:07 +02001262 if (global.sps_lim != 0) {
1263 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1264 err_code |= ERR_ALERT;
1265 goto out;
1266 }
1267 if (*(args[1]) == 0) {
1268 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1269 err_code |= ERR_ALERT | ERR_FATAL;
1270 goto out;
1271 }
1272 global.sps_lim = atol(args[1]);
1273 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001274 else if (!strcmp(args[0], "maxsslrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001275 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1276 goto out;
Willy Tarreaue43d5322013-10-07 20:01:52 +02001277 if (global.ssl_lim != 0) {
1278 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1279 err_code |= ERR_ALERT;
1280 goto out;
1281 }
1282 if (*(args[1]) == 0) {
1283 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1284 err_code |= ERR_ALERT | ERR_FATAL;
1285 goto out;
1286 }
1287 global.ssl_lim = atol(args[1]);
1288 }
William Lallemandd85f9172012-11-09 17:05:39 +01001289 else if (!strcmp(args[0], "maxcomprate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001290 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1291 goto out;
William Lallemandd85f9172012-11-09 17:05:39 +01001292 if (*(args[1]) == 0) {
1293 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1294 err_code |= ERR_ALERT | ERR_FATAL;
1295 goto out;
1296 }
1297 global.comp_rate_lim = atoi(args[1]) * 1024;
1298 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001299 else if (!strcmp(args[0], "maxpipes")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001300 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1301 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001302 if (global.maxpipes != 0) {
1303 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001304 err_code |= ERR_ALERT;
1305 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001306 }
1307 if (*(args[1]) == 0) {
1308 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001309 err_code |= ERR_ALERT | ERR_FATAL;
1310 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001311 }
1312 global.maxpipes = atol(args[1]);
1313 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001314 else if (!strcmp(args[0], "maxzlibmem")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001315 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1316 goto out;
William Lallemand9d5f5482012-11-07 16:12:57 +01001317 if (*(args[1]) == 0) {
1318 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1319 err_code |= ERR_ALERT | ERR_FATAL;
1320 goto out;
1321 }
William Lallemande3a7d992012-11-20 11:25:20 +01001322 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001323 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001324 else if (!strcmp(args[0], "maxcompcpuusage")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001325 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1326 goto out;
William Lallemand072a2bf2012-11-20 17:01:01 +01001327 if (*(args[1]) == 0) {
1328 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1329 err_code |= ERR_ALERT | ERR_FATAL;
1330 goto out;
1331 }
1332 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001333 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001334 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 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001338 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001339
Willy Tarreaubaaee002006-06-26 02:48:02 +02001340 else if (!strcmp(args[0], "ulimit-n")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001341 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1342 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001343 if (global.rlimit_nofile != 0) {
1344 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001345 err_code |= ERR_ALERT;
1346 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001347 }
1348 if (*(args[1]) == 0) {
1349 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001350 err_code |= ERR_ALERT | ERR_FATAL;
1351 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001352 }
1353 global.rlimit_nofile = atol(args[1]);
1354 }
1355 else if (!strcmp(args[0], "chroot")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001356 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1357 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001358 if (global.chroot != NULL) {
1359 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001360 err_code |= ERR_ALERT;
1361 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001362 }
1363 if (*(args[1]) == 0) {
1364 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001365 err_code |= ERR_ALERT | ERR_FATAL;
1366 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001367 }
1368 global.chroot = strdup(args[1]);
1369 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001370 else if (!strcmp(args[0], "description")) {
1371 int i, len=0;
1372 char *d;
1373
1374 if (!*args[1]) {
1375 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1376 file, linenum, args[0]);
1377 err_code |= ERR_ALERT | ERR_FATAL;
1378 goto out;
1379 }
1380
Willy Tarreau348acfe2014-04-14 15:00:39 +02001381 for (i = 1; *args[i]; i++)
1382 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001383
1384 if (global.desc)
1385 free(global.desc);
1386
1387 global.desc = d = (char *)calloc(1, len);
1388
Willy Tarreau348acfe2014-04-14 15:00:39 +02001389 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1390 for (i = 2; *args[i]; i++)
1391 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001392 }
1393 else if (!strcmp(args[0], "node")) {
1394 int i;
1395 char c;
1396
William Lallemand1a748ae2015-05-19 16:37:23 +02001397 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1398 goto out;
1399
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001400 for (i=0; args[1][i]; i++) {
1401 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001402 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1403 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001404 break;
1405 }
1406
1407 if (!i || args[1][i]) {
1408 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1409 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1410 file, linenum, args[0]);
1411 err_code |= ERR_ALERT | ERR_FATAL;
1412 goto out;
1413 }
1414
1415 if (global.node)
1416 free(global.node);
1417
1418 global.node = strdup(args[1]);
1419 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001420 else if (!strcmp(args[0], "pidfile")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001421 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1422 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001423 if (global.pidfile != NULL) {
1424 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001425 err_code |= ERR_ALERT;
1426 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001427 }
1428 if (*(args[1]) == 0) {
1429 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001430 err_code |= ERR_ALERT | ERR_FATAL;
1431 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001432 }
1433 global.pidfile = strdup(args[1]);
1434 }
Emeric Bruned760922010-10-22 17:59:25 +02001435 else if (!strcmp(args[0], "unix-bind")) {
1436 int cur_arg = 1;
1437 while (*(args[cur_arg])) {
1438 if (!strcmp(args[cur_arg], "prefix")) {
1439 if (global.unix_bind.prefix != NULL) {
1440 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1441 err_code |= ERR_ALERT;
1442 cur_arg += 2;
1443 continue;
1444 }
1445
1446 if (*(args[cur_arg+1]) == 0) {
1447 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1448 err_code |= ERR_ALERT | ERR_FATAL;
1449 goto out;
1450 }
1451 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1452 cur_arg += 2;
1453 continue;
1454 }
1455
1456 if (!strcmp(args[cur_arg], "mode")) {
1457
1458 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1459 cur_arg += 2;
1460 continue;
1461 }
1462
1463 if (!strcmp(args[cur_arg], "uid")) {
1464
1465 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1466 cur_arg += 2;
1467 continue;
1468 }
1469
1470 if (!strcmp(args[cur_arg], "gid")) {
1471
1472 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1473 cur_arg += 2;
1474 continue;
1475 }
1476
1477 if (!strcmp(args[cur_arg], "user")) {
1478 struct passwd *user;
1479
1480 user = getpwnam(args[cur_arg + 1]);
1481 if (!user) {
1482 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1483 file, linenum, args[0], args[cur_arg + 1 ]);
1484 err_code |= ERR_ALERT | ERR_FATAL;
1485 goto out;
1486 }
1487
1488 global.unix_bind.ux.uid = user->pw_uid;
1489 cur_arg += 2;
1490 continue;
1491 }
1492
1493 if (!strcmp(args[cur_arg], "group")) {
1494 struct group *group;
1495
1496 group = getgrnam(args[cur_arg + 1]);
1497 if (!group) {
1498 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1499 file, linenum, args[0], args[cur_arg + 1 ]);
1500 err_code |= ERR_ALERT | ERR_FATAL;
1501 goto out;
1502 }
1503
1504 global.unix_bind.ux.gid = group->gr_gid;
1505 cur_arg += 2;
1506 continue;
1507 }
1508
Willy Tarreaub48f9582011-09-05 01:17:06 +02001509 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001510 file, linenum, args[0]);
1511 err_code |= ERR_ALERT | ERR_FATAL;
1512 goto out;
1513 }
1514 }
William Lallemand0f99e342011-10-12 17:50:54 +02001515 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1516 /* delete previous herited or defined syslog servers */
1517 struct logsrv *back;
1518 struct logsrv *tmp;
1519
1520 if (*(args[1]) != 0) {
1521 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1522 err_code |= ERR_ALERT | ERR_FATAL;
1523 goto out;
1524 }
1525
1526 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1527 LIST_DEL(&tmp->list);
1528 free(tmp);
1529 }
1530 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001531 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001532 struct sockaddr_storage *sk;
1533 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001534 struct logsrv *logsrv;
Willy Tarreau18324f52014-06-27 18:10:07 +02001535 int arg = 0;
1536 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001537
William Lallemand1a748ae2015-05-19 16:37:23 +02001538 if (alertif_too_many_args(8, file, linenum, args, &err_code)) /* does not strictly check optional arguments */
1539 goto out;
1540
Willy Tarreaubaaee002006-06-26 02:48:02 +02001541 if (*(args[1]) == 0 || *(args[2]) == 0) {
1542 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001543 err_code |= ERR_ALERT | ERR_FATAL;
1544 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001545 }
William Lallemand0f99e342011-10-12 17:50:54 +02001546
1547 logsrv = calloc(1, sizeof(struct logsrv));
1548
Willy Tarreau18324f52014-06-27 18:10:07 +02001549 /* just after the address, a length may be specified */
1550 if (strcmp(args[arg+2], "len") == 0) {
1551 len = atoi(args[arg+3]);
1552 if (len < 80 || len > 65535) {
1553 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1554 file, linenum, args[arg+3]);
1555 err_code |= ERR_ALERT | ERR_FATAL;
1556 goto out;
1557 }
1558 logsrv->maxlen = len;
1559
1560 /* skip these two args */
1561 arg += 2;
1562 }
1563 else
1564 logsrv->maxlen = MAX_SYSLOG_LEN;
1565
1566 if (logsrv->maxlen > global.max_syslog_len) {
1567 global.max_syslog_len = logsrv->maxlen;
1568 logline = realloc(logline, global.max_syslog_len + 1);
1569 }
1570
William Lallemand1a748ae2015-05-19 16:37:23 +02001571 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
1572 goto out;
1573
Willy Tarreau18324f52014-06-27 18:10:07 +02001574 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001575 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001576 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001577 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001578 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001579 }
1580
William Lallemand0f99e342011-10-12 17:50:54 +02001581 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02001582 if (*(args[arg+3])) {
1583 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001584 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001585 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001586 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001587 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001588 }
1589 }
1590
William Lallemand0f99e342011-10-12 17:50:54 +02001591 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02001592 if (*(args[arg+4])) {
1593 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001594 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001595 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001596 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001597 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001598 }
1599 }
1600
Willy Tarreau72b8c1f2015-09-08 15:50:19 +02001601 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001602 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001603 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001604 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001605 free(logsrv);
1606 goto out;
1607 }
1608 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001609
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001610 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001611 if (port1 != port2) {
1612 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1613 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001614 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001615 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001616 goto out;
1617 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001618
William Lallemand0f99e342011-10-12 17:50:54 +02001619 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001620 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001621 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001622 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001623
William Lallemand0f99e342011-10-12 17:50:54 +02001624 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001625 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001626 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1627 char *name;
1628 int len;
1629
1630 if (global.log_send_hostname != NULL) {
1631 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1632 err_code |= ERR_ALERT;
1633 goto out;
1634 }
1635
1636 if (*(args[1]))
1637 name = args[1];
1638 else
1639 name = hostname;
1640
1641 len = strlen(name);
1642
1643 /* We'll add a space after the name to respect the log format */
1644 free(global.log_send_hostname);
1645 global.log_send_hostname = malloc(len + 2);
1646 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1647 }
Baptiste Assmann6bc89362015-08-23 09:22:25 +02001648 else if (!strcmp(args[0], "server-state-base")) { /* path base where HAProxy can find server state files */
1649 if (global.server_state_base != NULL) {
1650 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1651 err_code |= ERR_ALERT;
1652 goto out;
1653 }
1654
1655 if (!*(args[1])) {
1656 Alert("parsing [%s:%d] : '%s' expects one argument: a directory path.\n", file, linenum, args[0]);
1657 err_code |= ERR_FATAL;
1658 goto out;
1659 }
1660
1661 global.server_state_base = strdup(args[1]);
1662 }
Baptiste Assmanne0882262015-08-23 09:54:31 +02001663 else if (!strcmp(args[0], "server-state-file")) { /* path to the file where HAProxy can load the server states */
1664 if (global.server_state_file != NULL) {
1665 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1666 err_code |= ERR_ALERT;
1667 goto out;
1668 }
1669
1670 if (!*(args[1])) {
1671 Alert("parsing [%s:%d] : '%s' expect one argument: a file path.\n", file, linenum, args[0]);
1672 err_code |= ERR_FATAL;
1673 goto out;
1674 }
1675
1676 global.server_state_file = strdup(args[1]);
1677 }
Kevinm48936af2010-12-22 16:08:21 +00001678 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
William Lallemand1a748ae2015-05-19 16:37:23 +02001679 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1680 goto out;
Kevinm48936af2010-12-22 16:08:21 +00001681 if (*(args[1]) == 0) {
1682 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1683 err_code |= ERR_ALERT | ERR_FATAL;
1684 goto out;
1685 }
1686 free(global.log_tag);
1687 global.log_tag = strdup(args[1]);
1688 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001689 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
William Lallemand1a748ae2015-05-19 16:37:23 +02001690 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1691 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001692 if (global.spread_checks != 0) {
1693 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001694 err_code |= ERR_ALERT;
1695 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001696 }
1697 if (*(args[1]) == 0) {
1698 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001699 err_code |= ERR_ALERT | ERR_FATAL;
1700 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001701 }
1702 global.spread_checks = atol(args[1]);
1703 if (global.spread_checks < 0 || global.spread_checks > 50) {
1704 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001705 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001706 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001707 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001708 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1709 const char *err;
1710 unsigned int val;
1711
William Lallemand1a748ae2015-05-19 16:37:23 +02001712 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1713 goto out;
Willy Tarreau1746eec2014-04-25 10:46:47 +02001714 if (*(args[1]) == 0) {
1715 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1716 err_code |= ERR_ALERT | ERR_FATAL;
1717 goto out;
1718 }
1719
1720 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1721 if (err) {
1722 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1723 err_code |= ERR_ALERT | ERR_FATAL;
1724 }
1725 global.max_spread_checks = val;
1726 if (global.max_spread_checks < 0) {
1727 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1728 err_code |= ERR_ALERT | ERR_FATAL;
1729 }
1730 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001731 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1732#ifdef USE_CPU_AFFINITY
1733 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001734 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001735 unsigned long cpus = 0;
1736
1737 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001738 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001739 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001740 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001741 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001742 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001743 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001744 proc = atol(args[1]);
1745 if (proc >= 1 && proc <= LONGBITS)
1746 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001747 }
1748
1749 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001750 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",
1751 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001752 err_code |= ERR_ALERT | ERR_FATAL;
1753 goto out;
1754 }
1755
1756 cur_arg = 2;
1757 while (*args[cur_arg]) {
1758 unsigned int low, high;
1759
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001760 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001761 char *dash = strchr(args[cur_arg], '-');
1762
1763 low = high = str2uic(args[cur_arg]);
1764 if (dash)
1765 high = str2uic(dash + 1);
1766
1767 if (high < low) {
1768 unsigned int swap = low;
1769 low = high;
1770 high = swap;
1771 }
1772
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001773 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001774 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001775 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001776 err_code |= ERR_ALERT | ERR_FATAL;
1777 goto out;
1778 }
1779
1780 while (low <= high)
1781 cpus |= 1UL << low++;
1782 }
1783 else {
1784 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1785 file, linenum, args[0], args[cur_arg]);
1786 err_code |= ERR_ALERT | ERR_FATAL;
1787 goto out;
1788 }
1789 cur_arg++;
1790 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001791 for (i = 0; i < LONGBITS; i++)
1792 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001793 global.cpu_map[i] = cpus;
1794#else
1795 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1796 err_code |= ERR_ALERT | ERR_FATAL;
1797 goto out;
1798#endif
1799 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001800 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001801 struct cfg_kw_list *kwl;
1802 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001803 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001804
1805 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1806 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1807 if (kwl->kw[index].section != CFG_GLOBAL)
1808 continue;
1809 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001810 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001811 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001812 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001813 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001814 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001815 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001816 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001817 err_code |= ERR_WARN;
1818 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001819 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001820 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001821 }
1822 }
1823 }
1824
Willy Tarreaubaaee002006-06-26 02:48:02 +02001825 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001826 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001827 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001828
Willy Tarreau058e9072009-07-20 09:30:05 +02001829 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001830 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001831 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001832}
1833
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001834void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001835{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001836 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001837 defproxy.mode = PR_MODE_TCP;
1838 defproxy.state = PR_STNEW;
1839 defproxy.maxconn = cfg_maxpconn;
1840 defproxy.conn_retries = CONN_RETRIES;
Joseph Lynch726ab712015-05-11 23:25:34 -07001841 defproxy.redispatch_after = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001842
Simon Horman66183002013-02-23 10:16:43 +09001843 defproxy.defsrv.check.inter = DEF_CHKINTR;
1844 defproxy.defsrv.check.fastinter = 0;
1845 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001846 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1847 defproxy.defsrv.agent.fastinter = 0;
1848 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001849 defproxy.defsrv.check.rise = DEF_RISETIME;
1850 defproxy.defsrv.check.fall = DEF_FALLTIME;
1851 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1852 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001853 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001854 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001855 defproxy.defsrv.maxqueue = 0;
1856 defproxy.defsrv.minconn = 0;
1857 defproxy.defsrv.maxconn = 0;
1858 defproxy.defsrv.slowstart = 0;
1859 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1860 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1861 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Simon Horman64e34162015-02-06 11:11:57 +09001862
1863 defproxy.email_alert.level = LOG_ALERT;
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02001864 defproxy.load_server_state_from_file = PR_SRV_STATE_FILE_UNSPEC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001865}
1866
Willy Tarreauade5ec42010-01-28 19:33:49 +01001867
Willy Tarreau63af98d2014-05-18 08:11:41 +02001868/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1869 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1870 * ERR_FATAL in case of error.
1871 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001872static int create_cond_regex_rule(const char *file, int line,
1873 struct proxy *px, int dir, int action, int flags,
1874 const char *cmd, const char *reg, const char *repl,
1875 const char **cond_start)
1876{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001877 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001878 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001879 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001880 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001881 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001882 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001883 int cs;
1884 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001885
1886 if (px == &defproxy) {
1887 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001888 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001889 goto err;
1890 }
1891
1892 if (*reg == 0) {
1893 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001894 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001895 goto err;
1896 }
1897
1898 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001899 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001900
Willy Tarreau5321c422010-01-28 20:35:13 +01001901 if (cond_start &&
1902 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001903 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1904 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1905 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001906 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001907 goto err;
1908 }
1909 }
1910 else if (cond_start && **cond_start) {
1911 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1912 file, line, cmd, *cond_start);
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
Willy Tarreau63af98d2014-05-18 08:11:41 +02001917 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001918 (dir == SMP_OPT_DIR_REQ) ?
1919 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1920 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1921 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001922
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001923 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001924 if (!preg) {
1925 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001926 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001927 goto err;
1928 }
1929
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001930 cs = !(flags & REG_ICASE);
1931 cap = !(flags & REG_NOSUB);
1932 error = NULL;
1933 if (!regex_comp(reg, preg, cs, cap, &error)) {
1934 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1935 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001936 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001937 goto err;
1938 }
1939
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001940 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001941 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001942 if (repl && err) {
1943 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1944 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001945 ret_code |= ERR_ALERT | ERR_FATAL;
1946 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001947 }
1948
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001949 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001950 ret_code |= ERR_WARN;
1951
1952 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001953
Willy Tarreau63af98d2014-05-18 08:11:41 +02001954 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001955 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001956 err:
1957 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001958 free(errmsg);
1959 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001960}
1961
Willy Tarreaubaaee002006-06-26 02:48:02 +02001962/*
William Lallemand51097192015-04-14 16:35:22 +02001963 * Parse a line in a <listen>, <frontend> or <backend> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001964 * Returns the error code, 0 if OK, or any combination of :
1965 * - ERR_ABORT: must abort ASAP
1966 * - ERR_FATAL: we can continue parsing but not start the service
1967 * - ERR_WARN: a warning has been emitted
1968 * - ERR_ALERT: an alert has been emitted
1969 * Only the two first ones can stop processing, the two others are just
1970 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001971 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001972int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1973{
1974 static struct peers *curpeers = NULL;
1975 struct peer *newpeer = NULL;
1976 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001977 struct bind_conf *bind_conf;
1978 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001979 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001980 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001981
1982 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001983 if (!*args[1]) {
1984 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001985 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001986 goto out;
1987 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001988
William Lallemand6e62fb62015-04-28 16:55:23 +02001989 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1990 goto out;
1991
Emeric Brun32da3c42010-09-23 18:39:19 +02001992 err = invalid_char(args[1]);
1993 if (err) {
1994 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1995 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001996 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001997 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001998 }
1999
2000 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
2001 /*
2002 * If there are two proxies with the same name only following
2003 * combinations are allowed:
2004 */
2005 if (strcmp(curpeers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002006 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 +02002007 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002008 err_code |= ERR_ALERT | ERR_FATAL;
Emeric Brun32da3c42010-09-23 18:39:19 +02002009 }
2010 }
2011
2012 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
2013 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2014 err_code |= ERR_ALERT | ERR_ABORT;
2015 goto out;
2016 }
2017
2018 curpeers->next = peers;
2019 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002020 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002021 curpeers->conf.line = linenum;
2022 curpeers->last_change = now.tv_sec;
2023 curpeers->id = strdup(args[1]);
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002024 curpeers->state = PR_STNEW;
Emeric Brun32da3c42010-09-23 18:39:19 +02002025 }
2026 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01002027 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01002028 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002029 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02002030
2031 if (!*args[2]) {
2032 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2033 file, linenum, args[0]);
2034 err_code |= ERR_ALERT | ERR_FATAL;
2035 goto out;
2036 }
2037
2038 err = invalid_char(args[1]);
2039 if (err) {
2040 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2041 file, linenum, *err, args[1]);
2042 err_code |= ERR_ALERT | ERR_FATAL;
2043 goto out;
2044 }
2045
2046 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
2047 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2048 err_code |= ERR_ALERT | ERR_ABORT;
2049 goto out;
2050 }
2051
2052 /* the peers are linked backwards first */
2053 curpeers->count++;
2054 newpeer->next = curpeers->remote;
2055 curpeers->remote = newpeer;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002056 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002057 newpeer->conf.line = linenum;
2058
2059 newpeer->last_change = now.tv_sec;
2060 newpeer->id = strdup(args[1]);
2061
Willy Tarreau72b8c1f2015-09-08 15:50:19 +02002062 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002063 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01002064 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002065 err_code |= ERR_ALERT | ERR_FATAL;
2066 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002067 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01002068
2069 proto = protocol_by_family(sk->ss_family);
2070 if (!proto || !proto->connect) {
2071 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2072 file, linenum, args[0], args[1]);
2073 err_code |= ERR_ALERT | ERR_FATAL;
2074 goto out;
2075 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002076
2077 if (port1 != port2) {
2078 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2079 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002080 err_code |= ERR_ALERT | ERR_FATAL;
2081 goto out;
2082 }
2083
Willy Tarreau2aa38802013-02-20 19:20:59 +01002084 if (!port1) {
2085 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port 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 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002090
Emeric Brun32da3c42010-09-23 18:39:19 +02002091 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002092 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002093 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02002094 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02002095
Emeric Brun32da3c42010-09-23 18:39:19 +02002096 if (strcmp(newpeer->id, localpeer) == 0) {
2097 /* Current is local peer, it define a frontend */
2098 newpeer->local = 1;
Emeric Brunb3971ab2015-05-12 18:49:09 +02002099 peers->local = newpeer;
Emeric Brun32da3c42010-09-23 18:39:19 +02002100
2101 if (!curpeers->peers_fe) {
2102 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
2103 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2104 err_code |= ERR_ALERT | ERR_ABORT;
2105 goto out;
2106 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002107
Willy Tarreau237250c2011-07-29 01:49:03 +02002108 init_new_proxy(curpeers->peers_fe);
2109 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02002110 curpeers->peers_fe->id = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002111 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
2112 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau91d96282015-03-13 15:47:26 +01002113 peers_setup_frontend(curpeers->peers_fe);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002114
2115 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
2116
Willy Tarreau902636f2013-03-10 19:44:48 +01002117 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
2118 if (errmsg && *errmsg) {
2119 indent_msg(&errmsg, 2);
2120 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002121 }
2122 else
2123 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
2124 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002125 err_code |= ERR_FATAL;
2126 goto out;
2127 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02002128
2129 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01002130 l->maxaccept = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002131 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
2132 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
Willy Tarreau9903f0e2015-04-04 18:50:31 +02002133 l->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02002134 l->handler = process_stream;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002135 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01002136 l->default_target = ((struct proxy *)curpeers->peers_fe)->default_target;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002137 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
2138 global.maxsock += l->maxconn;
2139 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002140 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01002141 else {
2142 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
2143 file, linenum, args[0], args[1],
2144 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
2145 err_code |= ERR_FATAL;
2146 goto out;
2147 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002148 }
2149 } /* neither "peer" nor "peers" */
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002150 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
2151 curpeers->state = PR_STSTOPPED;
2152 }
2153 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
2154 curpeers->state = PR_STNEW;
2155 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002156 else if (*args[0] != 0) {
2157 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2158 err_code |= ERR_ALERT | ERR_FATAL;
2159 goto out;
2160 }
2161
2162out:
Willy Tarreau902636f2013-03-10 19:44:48 +01002163 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02002164 return err_code;
2165}
2166
Baptiste Assmann325137d2015-04-13 23:40:55 +02002167/*
2168 * Parse a <resolvers> section.
2169 * Returns the error code, 0 if OK, or any combination of :
2170 * - ERR_ABORT: must abort ASAP
2171 * - ERR_FATAL: we can continue parsing but not start the service
2172 * - ERR_WARN: a warning has been emitted
2173 * - ERR_ALERT: an alert has been emitted
2174 * Only the two first ones can stop processing, the two others are just
2175 * indicators.
2176 */
2177int cfg_parse_resolvers(const char *file, int linenum, char **args, int kwm)
2178{
2179 static struct dns_resolvers *curr_resolvers = NULL;
2180 struct dns_nameserver *newnameserver = NULL;
2181 const char *err;
2182 int err_code = 0;
2183 char *errmsg = NULL;
2184
2185 if (strcmp(args[0], "resolvers") == 0) { /* new resolvers section */
2186 if (!*args[1]) {
2187 Alert("parsing [%s:%d] : missing name for resolvers section.\n", file, linenum);
2188 err_code |= ERR_ALERT | ERR_ABORT;
2189 goto out;
2190 }
2191
2192 err = invalid_char(args[1]);
2193 if (err) {
2194 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2195 file, linenum, *err, args[0], args[1]);
2196 err_code |= ERR_ALERT | ERR_ABORT;
2197 goto out;
2198 }
2199
2200 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
2201 /* Error if two resolvers owns the same name */
2202 if (strcmp(curr_resolvers->id, args[1]) == 0) {
2203 Alert("Parsing [%s:%d]: resolvers '%s' has same name as another resolvers (declared at %s:%d).\n",
2204 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2205 err_code |= ERR_ALERT | ERR_ABORT;
2206 }
2207 }
2208
2209 if ((curr_resolvers = (struct dns_resolvers *)calloc(1, sizeof(struct dns_resolvers))) == NULL) {
2210 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2211 err_code |= ERR_ALERT | ERR_ABORT;
2212 goto out;
2213 }
2214
2215 /* default values */
2216 LIST_ADDQ(&dns_resolvers, &curr_resolvers->list);
2217 curr_resolvers->conf.file = strdup(file);
2218 curr_resolvers->conf.line = linenum;
2219 curr_resolvers->id = strdup(args[1]);
2220 curr_resolvers->query_ids = EB_ROOT;
2221 /* default hold period for valid is 10s */
Baptiste Assmann4c5490a2015-07-14 21:42:49 +02002222 curr_resolvers->hold.valid = 10000;
2223 curr_resolvers->timeout.retry = 1000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002224 curr_resolvers->resolve_retries = 3;
2225 LIST_INIT(&curr_resolvers->nameserver_list);
2226 LIST_INIT(&curr_resolvers->curr_resolution);
2227 }
2228 else if (strcmp(args[0], "nameserver") == 0) { /* nameserver definition */
2229 struct sockaddr_storage *sk;
2230 int port1, port2;
2231 struct protocol *proto;
2232
2233 if (!*args[2]) {
2234 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2235 file, linenum, args[0]);
2236 err_code |= ERR_ALERT | ERR_FATAL;
2237 goto out;
2238 }
2239
2240 err = invalid_char(args[1]);
2241 if (err) {
2242 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2243 file, linenum, *err, args[1]);
2244 err_code |= ERR_ALERT | ERR_FATAL;
2245 goto out;
2246 }
2247
2248 if ((newnameserver = (struct dns_nameserver *)calloc(1, sizeof(struct dns_nameserver))) == NULL) {
2249 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2250 err_code |= ERR_ALERT | ERR_ABORT;
2251 goto out;
2252 }
2253
2254 /* the nameservers are linked backward first */
2255 LIST_ADDQ(&curr_resolvers->nameserver_list, &newnameserver->list);
2256 curr_resolvers->count_nameservers++;
2257 newnameserver->resolvers = curr_resolvers;
2258 newnameserver->conf.file = strdup(file);
2259 newnameserver->conf.line = linenum;
2260 newnameserver->id = strdup(args[1]);
2261
Willy Tarreau72b8c1f2015-09-08 15:50:19 +02002262 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002263 if (!sk) {
2264 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2265 err_code |= ERR_ALERT | ERR_FATAL;
2266 goto out;
2267 }
2268
2269 proto = protocol_by_family(sk->ss_family);
2270 if (!proto || !proto->connect) {
2271 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2272 file, linenum, args[0], args[1]);
2273 err_code |= ERR_ALERT | ERR_FATAL;
2274 goto out;
2275 }
2276
2277 if (port1 != port2) {
2278 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2279 file, linenum, args[0], args[1], args[2]);
2280 err_code |= ERR_ALERT | ERR_FATAL;
2281 goto out;
2282 }
2283
2284 newnameserver->addr = *sk;
2285 }
2286 else if (strcmp(args[0], "hold") == 0) { /* hold periods */
2287 const char *res;
2288 unsigned int time;
2289
2290 if (!*args[2]) {
2291 Alert("parsing [%s:%d] : '%s' expects an <event> and a <time> as arguments.\n",
2292 file, linenum, args[0]);
2293 Alert("<event> can be either 'valid', 'nx', 'refused', 'timeout', or 'other'\n");
2294 err_code |= ERR_ALERT | ERR_FATAL;
2295 goto out;
2296 }
2297 res = parse_time_err(args[2], &time, TIME_UNIT_MS);
2298 if (res) {
2299 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2300 file, linenum, *res, args[0]);
2301 err_code |= ERR_ALERT | ERR_FATAL;
2302 goto out;
2303 }
2304 if (strcmp(args[1], "valid") == 0)
2305 curr_resolvers->hold.valid = time;
2306 else {
2307 Alert("parsing [%s:%d] : '%s' unknown <event>: '%s', expects 'valid'\n",
2308 file, linenum, args[0], args[1]);
2309 err_code |= ERR_ALERT | ERR_FATAL;
2310 goto out;
2311 }
2312
2313 }
2314 else if (strcmp(args[0], "resolve_retries") == 0) {
2315 if (!*args[1]) {
2316 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2317 file, linenum, args[0]);
2318 err_code |= ERR_ALERT | ERR_FATAL;
2319 goto out;
2320 }
2321 curr_resolvers->resolve_retries = atoi(args[1]);
2322 }
2323 else if (strcmp(args[0], "timeout") == 0) {
2324 const char *res;
2325 unsigned int timeout_retry;
2326
2327 if (!*args[2]) {
2328 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments.\n",
2329 file, linenum, args[0]);
2330 err_code |= ERR_ALERT | ERR_FATAL;
2331 goto out;
2332 }
2333 res = parse_time_err(args[2], &timeout_retry, TIME_UNIT_MS);
2334 if (res) {
2335 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2336 file, linenum, *res, args[0]);
2337 err_code |= ERR_ALERT | ERR_FATAL;
2338 goto out;
2339 }
2340 curr_resolvers->timeout.retry = timeout_retry;
2341 } /* neither "nameserver" nor "resolvers" */
2342 else if (*args[0] != 0) {
2343 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2344 err_code |= ERR_ALERT | ERR_FATAL;
2345 goto out;
2346 }
2347
2348 out:
2349 free(errmsg);
2350 return err_code;
2351}
Simon Horman0d16a402015-01-30 11:22:58 +09002352
2353/*
William Lallemand51097192015-04-14 16:35:22 +02002354 * Parse a line in a <listen>, <frontend> or <backend> section.
Simon Horman0d16a402015-01-30 11:22:58 +09002355 * Returns the error code, 0 if OK, or any combination of :
2356 * - ERR_ABORT: must abort ASAP
2357 * - ERR_FATAL: we can continue parsing but not start the service
2358 * - ERR_WARN: a warning has been emitted
2359 * - ERR_ALERT: an alert has been emitted
2360 * Only the two first ones can stop processing, the two others are just
2361 * indicators.
2362 */
2363int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
2364{
2365 static struct mailers *curmailers = NULL;
2366 struct mailer *newmailer = NULL;
2367 const char *err;
2368 int err_code = 0;
2369 char *errmsg = NULL;
2370
2371 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
2372 if (!*args[1]) {
2373 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
2374 err_code |= ERR_ALERT | ERR_ABORT;
2375 goto out;
2376 }
2377
2378 err = invalid_char(args[1]);
2379 if (err) {
2380 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2381 file, linenum, *err, args[0], args[1]);
2382 err_code |= ERR_ALERT | ERR_ABORT;
2383 goto out;
2384 }
2385
2386 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
2387 /*
2388 * If there are two proxies with the same name only following
2389 * combinations are allowed:
2390 */
2391 if (strcmp(curmailers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002392 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 +09002393 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002394 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman0d16a402015-01-30 11:22:58 +09002395 }
2396 }
2397
2398 if ((curmailers = (struct mailers *)calloc(1, sizeof(struct mailers))) == NULL) {
2399 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2400 err_code |= ERR_ALERT | ERR_ABORT;
2401 goto out;
2402 }
2403
2404 curmailers->next = mailers;
2405 mailers = curmailers;
2406 curmailers->conf.file = strdup(file);
2407 curmailers->conf.line = linenum;
2408 curmailers->id = strdup(args[1]);
2409 }
2410 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
2411 struct sockaddr_storage *sk;
2412 int port1, port2;
2413 struct protocol *proto;
2414
2415 if (!*args[2]) {
2416 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2417 file, linenum, args[0]);
2418 err_code |= ERR_ALERT | ERR_FATAL;
2419 goto out;
2420 }
2421
2422 err = invalid_char(args[1]);
2423 if (err) {
2424 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2425 file, linenum, *err, args[1]);
2426 err_code |= ERR_ALERT | ERR_FATAL;
2427 goto out;
2428 }
2429
2430 if ((newmailer = (struct mailer *)calloc(1, sizeof(struct mailer))) == NULL) {
2431 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2432 err_code |= ERR_ALERT | ERR_ABORT;
2433 goto out;
2434 }
2435
2436 /* the mailers are linked backwards first */
2437 curmailers->count++;
2438 newmailer->next = curmailers->mailer_list;
2439 curmailers->mailer_list = newmailer;
2440 newmailer->mailers = curmailers;
2441 newmailer->conf.file = strdup(file);
2442 newmailer->conf.line = linenum;
2443
2444 newmailer->id = strdup(args[1]);
2445
Willy Tarreau72b8c1f2015-09-08 15:50:19 +02002446 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL);
Simon Horman0d16a402015-01-30 11:22:58 +09002447 if (!sk) {
2448 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2449 err_code |= ERR_ALERT | ERR_FATAL;
2450 goto out;
2451 }
2452
2453 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002454 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2455 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002456 file, linenum, args[0], args[1]);
2457 err_code |= ERR_ALERT | ERR_FATAL;
2458 goto out;
2459 }
2460
2461 if (port1 != port2) {
2462 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2463 file, linenum, args[0], args[1], args[2]);
2464 err_code |= ERR_ALERT | ERR_FATAL;
2465 goto out;
2466 }
2467
2468 if (!port1) {
2469 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port 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 newmailer->addr = *sk;
2476 newmailer->proto = proto;
2477 newmailer->xprt = &raw_sock;
2478 newmailer->sock_init_arg = NULL;
2479 } /* neither "mailer" nor "mailers" */
2480 else if (*args[0] != 0) {
2481 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2482 err_code |= ERR_ALERT | ERR_FATAL;
2483 goto out;
2484 }
2485
2486out:
2487 free(errmsg);
2488 return err_code;
2489}
2490
Simon Horman9dc49962015-01-30 11:22:59 +09002491static void free_email_alert(struct proxy *p)
2492{
2493 free(p->email_alert.mailers.name);
2494 p->email_alert.mailers.name = NULL;
2495 free(p->email_alert.from);
2496 p->email_alert.from = NULL;
2497 free(p->email_alert.to);
2498 p->email_alert.to = NULL;
2499 free(p->email_alert.myhostname);
2500 p->email_alert.myhostname = NULL;
2501}
2502
Willy Tarreau3842f002009-06-14 11:39:52 +02002503int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002504{
2505 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002506 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002507 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002508 int rc;
2509 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002510 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002511 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002512 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002513 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002514 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002515
Willy Tarreau977b8e42006-12-29 14:19:17 +01002516 if (!strcmp(args[0], "listen"))
2517 rc = PR_CAP_LISTEN;
2518 else if (!strcmp(args[0], "frontend"))
2519 rc = PR_CAP_FE | PR_CAP_RS;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02002520 else if (!strcmp(args[0], "backend"))
Willy Tarreau977b8e42006-12-29 14:19:17 +01002521 rc = PR_CAP_BE | PR_CAP_RS;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002522 else
2523 rc = PR_CAP_NONE;
2524
2525 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002526 if (!*args[1]) {
2527 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
2528 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
2529 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002530 err_code |= ERR_ALERT | ERR_ABORT;
2531 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002532 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002533
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002534 err = invalid_char(args[1]);
2535 if (err) {
2536 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2537 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002538 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002539 }
2540
Willy Tarreau8f50b682015-05-26 11:45:02 +02002541 curproxy = (rc & PR_CAP_FE) ? proxy_fe_by_name(args[1]) : proxy_be_by_name(args[1]);
2542 if (curproxy) {
2543 Alert("Parsing [%s:%d]: %s '%s' has the same name as %s '%s' declared at %s:%d.\n",
2544 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2545 curproxy->id, curproxy->conf.file, curproxy->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002546 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002547 }
2548
Willy Tarreaubaaee002006-06-26 02:48:02 +02002549 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
2550 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002551 err_code |= ERR_ALERT | ERR_ABORT;
2552 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002553 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002554
Willy Tarreau97cb7802010-01-03 20:23:58 +01002555 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002556 curproxy->next = proxy;
2557 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002558 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2559 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002560 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002561 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002562 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002563 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002564
William Lallemand6e62fb62015-04-28 16:55:23 +02002565 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2566 if (curproxy->cap & PR_CAP_FE)
2567 Alert("parsing [%s:%d] : please use the 'bind' keyword for listening addresses.\n", file, linenum);
2568 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002569 }
2570
2571 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002572 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002573 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002574
Willy Tarreaubaaee002006-06-26 02:48:02 +02002575 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002576 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002577 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002578 curproxy->no_options = defproxy.no_options;
2579 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002580 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002581 curproxy->except_net = defproxy.except_net;
2582 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002583 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002584 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002585
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002586 if (defproxy.fwdfor_hdr_len) {
2587 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2588 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2589 }
2590
Willy Tarreaub86db342009-11-30 11:50:16 +01002591 if (defproxy.orgto_hdr_len) {
2592 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2593 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2594 }
2595
Mark Lamourinec2247f02012-01-04 13:02:01 -05002596 if (defproxy.server_id_hdr_len) {
2597 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2598 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2599 }
2600
Willy Tarreau977b8e42006-12-29 14:19:17 +01002601 if (curproxy->cap & PR_CAP_FE) {
2602 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002603 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002604 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002605
2606 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002607 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2608 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002609
2610 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2611 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002612
Willy Tarreau977b8e42006-12-29 14:19:17 +01002613 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002614 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002615 curproxy->fullconn = defproxy.fullconn;
2616 curproxy->conn_retries = defproxy.conn_retries;
Joseph Lynch726ab712015-05-11 23:25:34 -07002617 curproxy->redispatch_after = defproxy.redispatch_after;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002618 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002619
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002620 if (defproxy.check_req) {
2621 curproxy->check_req = calloc(1, defproxy.check_len);
2622 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2623 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002624 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002625
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002626 if (defproxy.expect_str) {
2627 curproxy->expect_str = strdup(defproxy.expect_str);
2628 if (defproxy.expect_regex) {
2629 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002630 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2631 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002632 }
2633 }
2634
Willy Tarreau67402132012-05-31 20:40:20 +02002635 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002636 if (defproxy.cookie_name)
2637 curproxy->cookie_name = strdup(defproxy.cookie_name);
2638 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002639 if (defproxy.cookie_domain)
2640 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002641
Willy Tarreau31936852010-10-06 16:59:56 +02002642 if (defproxy.cookie_maxidle)
2643 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2644
2645 if (defproxy.cookie_maxlife)
2646 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2647
Emeric Brun647caf12009-06-30 17:57:00 +02002648 if (defproxy.rdp_cookie_name)
2649 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2650 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2651
Willy Tarreau01732802007-11-01 22:48:15 +01002652 if (defproxy.url_param_name)
2653 curproxy->url_param_name = strdup(defproxy.url_param_name);
2654 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002655
Benoitaffb4812009-03-25 13:02:10 +01002656 if (defproxy.hh_name)
2657 curproxy->hh_name = strdup(defproxy.hh_name);
2658 curproxy->hh_len = defproxy.hh_len;
2659 curproxy->hh_match_domain = defproxy.hh_match_domain;
2660
Willy Tarreauef9a3602012-12-08 22:29:20 +01002661 if (defproxy.conn_src.iface_name)
2662 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2663 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002664 curproxy->conn_src.opts = defproxy.conn_src.opts;
Willy Tarreau29fbe512015-08-20 19:35:14 +02002665#if defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002666 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002667#endif
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02002668 curproxy->load_server_state_from_file = defproxy.load_server_state_from_file;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002669 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002670
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002671 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002672 if (defproxy.capture_name)
2673 curproxy->capture_name = strdup(defproxy.capture_name);
2674 curproxy->capture_namelen = defproxy.capture_namelen;
2675 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002676 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002677
Willy Tarreau977b8e42006-12-29 14:19:17 +01002678 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002679 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002680 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002681 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002682 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002683 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002684 curproxy->mon_net = defproxy.mon_net;
2685 curproxy->mon_mask = defproxy.mon_mask;
2686 if (defproxy.monitor_uri)
2687 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2688 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002689 if (defproxy.defbe.name)
2690 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002691
2692 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002693 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2694 if (curproxy->conf.logformat_string &&
2695 curproxy->conf.logformat_string != default_http_log_format &&
2696 curproxy->conf.logformat_string != default_tcp_log_format &&
2697 curproxy->conf.logformat_string != clf_http_log_format)
2698 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2699
2700 if (defproxy.conf.lfs_file) {
2701 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2702 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2703 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002704 }
2705
2706 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002707 curproxy->timeout.connect = defproxy.timeout.connect;
2708 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002709 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002710 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002711 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002712 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002713 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002714 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002715 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002716 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002717 }
2718
Willy Tarreaubaaee002006-06-26 02:48:02 +02002719 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002720 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002721
2722 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002723 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002724 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002725 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002726 LIST_INIT(&node->list);
2727 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2728 }
2729
Willy Tarreau62a61232013-04-12 18:13:46 +02002730 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2731 if (curproxy->conf.uniqueid_format_string)
2732 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2733
Willy Tarreau094af4e2015-01-07 15:03:42 +01002734 if (defproxy.log_tag)
2735 curproxy->log_tag = strdup(defproxy.log_tag);
2736
Willy Tarreau62a61232013-04-12 18:13:46 +02002737 if (defproxy.conf.uif_file) {
2738 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2739 curproxy->conf.uif_line = defproxy.conf.uif_line;
2740 }
William Lallemanda73203e2012-03-12 12:48:57 +01002741
2742 /* copy default header unique id */
2743 if (defproxy.header_unique_id)
2744 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2745
William Lallemand82fe75c2012-10-23 10:25:10 +02002746 /* default compression options */
2747 if (defproxy.comp != NULL) {
2748 curproxy->comp = calloc(1, sizeof(struct comp));
2749 curproxy->comp->algos = defproxy.comp->algos;
2750 curproxy->comp->types = defproxy.comp->types;
2751 }
2752
Willy Tarreaubaaee002006-06-26 02:48:02 +02002753 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002754 curproxy->conf.used_listener_id = EB_ROOT;
2755 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002756
Simon Horman98637e52014-06-20 12:30:16 +09002757 if (defproxy.check_path)
2758 curproxy->check_path = strdup(defproxy.check_path);
2759 if (defproxy.check_command)
2760 curproxy->check_command = strdup(defproxy.check_command);
2761
Simon Horman9dc49962015-01-30 11:22:59 +09002762 if (defproxy.email_alert.mailers.name)
2763 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2764 if (defproxy.email_alert.from)
2765 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2766 if (defproxy.email_alert.to)
2767 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2768 if (defproxy.email_alert.myhostname)
2769 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09002770 curproxy->email_alert.level = defproxy.email_alert.level;
Simon Horman9dc49962015-01-30 11:22:59 +09002771
Willy Tarreau93893792009-07-23 13:19:11 +02002772 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002773 }
2774 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2775 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002776 /* FIXME-20070101: we should do this too at the end of the
2777 * config parsing to free all default values.
2778 */
William Lallemand6e62fb62015-04-28 16:55:23 +02002779 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2780 err_code |= ERR_ABORT;
2781 goto out;
2782 }
2783
Willy Tarreaua534fea2008-08-03 12:19:50 +02002784 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002785 free(defproxy.check_command);
2786 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002787 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002788 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002789 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002790 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002791 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002792 free(defproxy.capture_name);
2793 free(defproxy.monitor_uri);
2794 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002795 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002796 free(defproxy.fwdfor_hdr_name);
2797 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002798 free(defproxy.orgto_hdr_name);
2799 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002800 free(defproxy.server_id_hdr_name);
2801 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002802 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002803 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002804 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002805 free(defproxy.expect_regex);
2806 defproxy.expect_regex = NULL;
2807 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002808
Willy Tarreau62a61232013-04-12 18:13:46 +02002809 if (defproxy.conf.logformat_string != default_http_log_format &&
2810 defproxy.conf.logformat_string != default_tcp_log_format &&
2811 defproxy.conf.logformat_string != clf_http_log_format)
2812 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002813
Willy Tarreau62a61232013-04-12 18:13:46 +02002814 free(defproxy.conf.uniqueid_format_string);
2815 free(defproxy.conf.lfs_file);
2816 free(defproxy.conf.uif_file);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002817 free(defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09002818 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02002819
Willy Tarreaua534fea2008-08-03 12:19:50 +02002820 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002821 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002822
Willy Tarreaubaaee002006-06-26 02:48:02 +02002823 /* we cannot free uri_auth because it might already be used */
2824 init_default_instance();
2825 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002826 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2827 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002828 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002829 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002830 }
2831 else if (curproxy == NULL) {
2832 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002833 err_code |= ERR_ALERT | ERR_FATAL;
2834 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002835 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002836
2837 /* update the current file and line being parsed */
2838 curproxy->conf.args.file = curproxy->conf.file;
2839 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002840
2841 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002842 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2843 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2844 if (err_code & ERR_FATAL)
2845 goto out;
2846 }
2847 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002848 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002849 int cur_arg;
2850
Willy Tarreaubaaee002006-06-26 02:48:02 +02002851 if (curproxy == &defproxy) {
2852 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002853 err_code |= ERR_ALERT | ERR_FATAL;
2854 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002855 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002856 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002857 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002858
Willy Tarreau24709282013-03-10 21:32:12 +01002859 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002860 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002861 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002862 err_code |= ERR_ALERT | ERR_FATAL;
2863 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002864 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002865
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002866 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002867
2868 /* use default settings for unix sockets */
2869 bind_conf->ux.uid = global.unix_bind.ux.uid;
2870 bind_conf->ux.gid = global.unix_bind.ux.gid;
2871 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002872
2873 /* NOTE: the following line might create several listeners if there
2874 * are comma-separated IPs or port ranges. So all further processing
2875 * will have to be applied to all listeners created after last_listen.
2876 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002877 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2878 if (errmsg && *errmsg) {
2879 indent_msg(&errmsg, 2);
2880 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002881 }
2882 else
2883 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2884 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002885 err_code |= ERR_ALERT | ERR_FATAL;
2886 goto out;
2887 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002888
Willy Tarreau4348fad2012-09-20 16:48:07 +02002889 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2890 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002891 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002892 }
2893
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002894 cur_arg = 2;
2895 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002896 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002897 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002898 char *err;
2899
Willy Tarreau26982662012-09-12 23:17:10 +02002900 kw = bind_find_kw(args[cur_arg]);
2901 if (kw) {
2902 char *err = NULL;
2903 int code;
2904
2905 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002906 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2907 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002908 cur_arg += 1 + kw->skip ;
2909 err_code |= ERR_ALERT | ERR_FATAL;
2910 goto out;
2911 }
2912
Willy Tarreau4348fad2012-09-20 16:48:07 +02002913 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002914 err_code |= code;
2915
2916 if (code) {
2917 if (err && *err) {
2918 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002919 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002920 }
2921 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002922 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2923 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002924 if (code & ERR_FATAL) {
2925 free(err);
2926 cur_arg += 1 + kw->skip;
2927 goto out;
2928 }
2929 }
2930 free(err);
2931 cur_arg += 1 + kw->skip;
2932 continue;
2933 }
2934
Willy Tarreau8638f482012-09-18 18:01:17 +02002935 err = NULL;
2936 if (!bind_dumped) {
2937 bind_dump_kws(&err);
2938 indent_msg(&err, 4);
2939 bind_dumped = 1;
2940 }
2941
2942 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2943 file, linenum, args[0], args[1], args[cur_arg],
2944 err ? " Registered keywords :" : "", err ? err : "");
2945 free(err);
2946
Willy Tarreau93893792009-07-23 13:19:11 +02002947 err_code |= ERR_ALERT | ERR_FATAL;
2948 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002949 }
Willy Tarreau93893792009-07-23 13:19:11 +02002950 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002951 }
2952 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002953 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002954 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2955 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002956 err_code |= ERR_ALERT | ERR_FATAL;
2957 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002958 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002959 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002960 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002961
Willy Tarreaubaaee002006-06-26 02:48:02 +02002962 /* flush useless bits */
2963 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002964 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002965 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002966 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002967 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002968 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002969
William Lallemanddf1425a2015-04-28 20:17:49 +02002970 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2971 goto out;
2972
Willy Tarreau1c47f852006-07-09 08:22:27 +02002973 if (!*args[1]) {
2974 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2975 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002976 err_code |= ERR_ALERT | ERR_FATAL;
2977 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002978 }
2979
Willy Tarreaua534fea2008-08-03 12:19:50 +02002980 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002981 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002982 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002983 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002984 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2985
Willy Tarreau93893792009-07-23 13:19:11 +02002986 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002987 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002988 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
William Lallemanddf1425a2015-04-28 20:17:49 +02002989 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2990 goto out;
2991
Willy Tarreaubaaee002006-06-26 02:48:02 +02002992 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2993 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2994 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2995 else {
2996 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002997 err_code |= ERR_ALERT | ERR_FATAL;
2998 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002999 }
3000 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003001 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003002 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003003
3004 if (curproxy == &defproxy) {
3005 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3006 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003007 err_code |= ERR_ALERT | ERR_FATAL;
3008 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003009 }
3010
William Lallemanddf1425a2015-04-28 20:17:49 +02003011 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3012 goto out;
3013
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003014 if (!*args[1]) {
3015 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3016 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003017 err_code |= ERR_ALERT | ERR_FATAL;
3018 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003019 }
3020
3021 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003022 curproxy->conf.id.key = curproxy->uuid;
Willy Tarreau0d1fdf72015-05-27 16:44:02 +02003023 curproxy->options |= PR_O_FORCED_ID;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003024
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003025 if (curproxy->uuid <= 0) {
3026 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003027 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003028 err_code |= ERR_ALERT | ERR_FATAL;
3029 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003030 }
3031
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003032 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
3033 if (node) {
3034 struct proxy *target = container_of(node, struct proxy, conf.id);
3035 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
3036 file, linenum, proxy_type_str(curproxy), curproxy->id,
3037 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
3038 err_code |= ERR_ALERT | ERR_FATAL;
3039 goto out;
3040 }
3041 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003042 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003043 else if (!strcmp(args[0], "description")) {
3044 int i, len=0;
3045 char *d;
3046
Cyril Bonté99ed3272010-01-24 23:29:44 +01003047 if (curproxy == &defproxy) {
3048 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3049 file, linenum, args[0]);
3050 err_code |= ERR_ALERT | ERR_FATAL;
3051 goto out;
3052 }
3053
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003054 if (!*args[1]) {
3055 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
3056 file, linenum, args[0]);
3057 return -1;
3058 }
3059
Willy Tarreau348acfe2014-04-14 15:00:39 +02003060 for (i = 1; *args[i]; i++)
3061 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003062
3063 d = (char *)calloc(1, len);
3064 curproxy->desc = d;
3065
Willy Tarreau348acfe2014-04-14 15:00:39 +02003066 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
3067 for (i = 2; *args[i]; i++)
3068 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003069
3070 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003071 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
William Lallemanddf1425a2015-04-28 20:17:49 +02003072 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3073 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003074 curproxy->state = PR_STSTOPPED;
3075 }
3076 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
William Lallemanddf1425a2015-04-28 20:17:49 +02003077 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3078 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003079 curproxy->state = PR_STNEW;
3080 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003081 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
3082 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003083 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003084
3085 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003086 unsigned int low, high;
3087
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003088 if (strcmp(args[cur_arg], "all") == 0) {
3089 set = 0;
3090 break;
3091 }
3092 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003093 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003094 }
3095 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003096 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003097 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01003098 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003099 char *dash = strchr(args[cur_arg], '-');
3100
3101 low = high = str2uic(args[cur_arg]);
3102 if (dash)
3103 high = str2uic(dash + 1);
3104
3105 if (high < low) {
3106 unsigned int swap = low;
3107 low = high;
3108 high = swap;
3109 }
3110
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003111 if (low < 1 || high > LONGBITS) {
3112 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
3113 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02003114 err_code |= ERR_ALERT | ERR_FATAL;
3115 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003116 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01003117 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003118 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003119 }
3120 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003121 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
3122 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003123 err_code |= ERR_ALERT | ERR_FATAL;
3124 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003125 }
3126 cur_arg++;
3127 }
3128 curproxy->bind_proc = set;
3129 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003130 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02003131 if (curproxy == &defproxy) {
3132 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003133 err_code |= ERR_ALERT | ERR_FATAL;
3134 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003135 }
3136
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003137 err = invalid_char(args[1]);
3138 if (err) {
3139 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
3140 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003141 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003142 }
3143
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01003144 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003145 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
3146 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003147 err_code |= ERR_ALERT | ERR_FATAL;
3148 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003149 }
3150 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003151 else if (!strcmp(args[0], "cookie")) { /* cookie name */
3152 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003153
Willy Tarreau977b8e42006-12-29 14:19:17 +01003154 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003155 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003156
Willy Tarreaubaaee002006-06-26 02:48:02 +02003157 if (*(args[1]) == 0) {
3158 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
3159 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003160 err_code |= ERR_ALERT | ERR_FATAL;
3161 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003162 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003163
Willy Tarreau67402132012-05-31 20:40:20 +02003164 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003165 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01003166 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003167 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003168 curproxy->cookie_name = strdup(args[1]);
3169 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003170
Willy Tarreaubaaee002006-06-26 02:48:02 +02003171 cur_arg = 2;
3172 while (*(args[cur_arg])) {
3173 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003174 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003175 }
3176 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003177 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003178 }
3179 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003180 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003181 }
3182 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003183 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003184 }
3185 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003186 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003187 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003188 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003189 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003190 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003191 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003192 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003193 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02003194 else if (!strcmp(args[cur_arg], "httponly")) {
3195 curproxy->ck_opts |= PR_CK_HTTPONLY;
3196 }
3197 else if (!strcmp(args[cur_arg], "secure")) {
3198 curproxy->ck_opts |= PR_CK_SECURE;
3199 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003200 else if (!strcmp(args[cur_arg], "domain")) {
3201 if (!*args[cur_arg + 1]) {
3202 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
3203 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003204 err_code |= ERR_ALERT | ERR_FATAL;
3205 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003206 }
3207
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003208 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003209 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003210 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
3211 " dots nor does not start with a dot."
3212 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003213 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003214 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003215 }
3216
3217 err = invalid_domainchar(args[cur_arg + 1]);
3218 if (err) {
3219 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
3220 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003221 err_code |= ERR_ALERT | ERR_FATAL;
3222 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003223 }
3224
Willy Tarreau68a897b2009-12-03 23:28:34 +01003225 if (!curproxy->cookie_domain) {
3226 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
3227 } else {
3228 /* one domain was already specified, add another one by
3229 * building the string which will be returned along with
3230 * the cookie.
3231 */
3232 char *new_ptr;
3233 int new_len = strlen(curproxy->cookie_domain) +
3234 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
3235 new_ptr = malloc(new_len);
3236 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
3237 free(curproxy->cookie_domain);
3238 curproxy->cookie_domain = new_ptr;
3239 }
Willy Tarreau31936852010-10-06 16:59:56 +02003240 cur_arg++;
3241 }
3242 else if (!strcmp(args[cur_arg], "maxidle")) {
3243 unsigned int maxidle;
3244 const char *res;
3245
3246 if (!*args[cur_arg + 1]) {
3247 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
3248 file, linenum, args[cur_arg]);
3249 err_code |= ERR_ALERT | ERR_FATAL;
3250 goto out;
3251 }
3252
3253 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
3254 if (res) {
3255 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3256 file, linenum, *res, args[cur_arg]);
3257 err_code |= ERR_ALERT | ERR_FATAL;
3258 goto out;
3259 }
3260 curproxy->cookie_maxidle = maxidle;
3261 cur_arg++;
3262 }
3263 else if (!strcmp(args[cur_arg], "maxlife")) {
3264 unsigned int maxlife;
3265 const char *res;
3266
3267 if (!*args[cur_arg + 1]) {
3268 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
3269 file, linenum, args[cur_arg]);
3270 err_code |= ERR_ALERT | ERR_FATAL;
3271 goto out;
3272 }
3273
3274 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
3275 if (res) {
3276 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3277 file, linenum, *res, args[cur_arg]);
3278 err_code |= ERR_ALERT | ERR_FATAL;
3279 goto out;
3280 }
3281 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003282 cur_arg++;
3283 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003284 else {
Willy Tarreau31936852010-10-06 16:59:56 +02003285 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 +02003286 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003287 err_code |= ERR_ALERT | ERR_FATAL;
3288 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003289 }
3290 cur_arg++;
3291 }
Willy Tarreau67402132012-05-31 20:40:20 +02003292 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003293 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
3294 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003295 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003296 }
3297
Willy Tarreau67402132012-05-31 20:40:20 +02003298 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003299 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
3300 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003301 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003302 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003303
Willy Tarreau67402132012-05-31 20:40:20 +02003304 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003305 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
3306 file, linenum);
3307 err_code |= ERR_ALERT | ERR_FATAL;
3308 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003309 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09003310 else if (!strcmp(args[0], "email-alert")) {
3311 if (*(args[1]) == 0) {
3312 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3313 file, linenum, args[0]);
3314 err_code |= ERR_ALERT | ERR_FATAL;
3315 goto out;
3316 }
3317
3318 if (!strcmp(args[1], "from")) {
3319 if (*(args[1]) == 0) {
3320 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3321 file, linenum, args[1]);
3322 err_code |= ERR_ALERT | ERR_FATAL;
3323 goto out;
3324 }
3325 free(curproxy->email_alert.from);
3326 curproxy->email_alert.from = strdup(args[2]);
3327 }
3328 else if (!strcmp(args[1], "mailers")) {
3329 if (*(args[1]) == 0) {
3330 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3331 file, linenum, args[1]);
3332 err_code |= ERR_ALERT | ERR_FATAL;
3333 goto out;
3334 }
3335 free(curproxy->email_alert.mailers.name);
3336 curproxy->email_alert.mailers.name = strdup(args[2]);
3337 }
3338 else if (!strcmp(args[1], "myhostname")) {
3339 if (*(args[1]) == 0) {
3340 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3341 file, linenum, args[1]);
3342 err_code |= ERR_ALERT | ERR_FATAL;
3343 goto out;
3344 }
3345 free(curproxy->email_alert.myhostname);
3346 curproxy->email_alert.myhostname = strdup(args[2]);
3347 }
Simon Horman64e34162015-02-06 11:11:57 +09003348 else if (!strcmp(args[1], "level")) {
3349 curproxy->email_alert.level = get_log_level(args[2]);
3350 if (curproxy->email_alert.level < 0) {
3351 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
3352 file, linenum, args[1], args[2]);
3353 err_code |= ERR_ALERT | ERR_FATAL;
3354 goto out;
3355 }
3356 }
Simon Horman9dc49962015-01-30 11:22:59 +09003357 else if (!strcmp(args[1], "to")) {
3358 if (*(args[1]) == 0) {
3359 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3360 file, linenum, args[1]);
3361 err_code |= ERR_ALERT | ERR_FATAL;
3362 goto out;
3363 }
3364 free(curproxy->email_alert.to);
3365 curproxy->email_alert.to = strdup(args[2]);
3366 }
3367 else {
3368 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
3369 file, linenum, args[1]);
3370 err_code |= ERR_ALERT | ERR_FATAL;
3371 goto out;
3372 }
Simon Horman64e34162015-02-06 11:11:57 +09003373 /* Indicate that the email_alert is at least partially configured */
3374 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09003375 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09003376 else if (!strcmp(args[0], "external-check")) {
3377 if (*(args[1]) == 0) {
3378 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3379 file, linenum, args[0]);
3380 err_code |= ERR_ALERT | ERR_FATAL;
3381 goto out;
3382 }
3383
3384 if (!strcmp(args[1], "command")) {
William Lallemanddf1425a2015-04-28 20:17:49 +02003385 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3386 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09003387 if (*(args[1]) == 0) {
3388 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3389 file, linenum, args[1]);
3390 err_code |= ERR_ALERT | ERR_FATAL;
3391 goto out;
3392 }
3393 free(curproxy->check_command);
3394 curproxy->check_command = strdup(args[2]);
3395 }
3396 else if (!strcmp(args[1], "path")) {
William Lallemanddf1425a2015-04-28 20:17:49 +02003397 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3398 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09003399 if (*(args[1]) == 0) {
3400 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3401 file, linenum, args[1]);
3402 err_code |= ERR_ALERT | ERR_FATAL;
3403 goto out;
3404 }
3405 free(curproxy->check_path);
3406 curproxy->check_path = strdup(args[2]);
3407 }
3408 else {
3409 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
3410 file, linenum, args[1]);
3411 err_code |= ERR_ALERT | ERR_FATAL;
3412 goto out;
3413 }
3414 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02003415 else if (!strcmp(args[0], "persist")) { /* persist */
3416 if (*(args[1]) == 0) {
3417 Alert("parsing [%s:%d] : missing persist method.\n",
3418 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003419 err_code |= ERR_ALERT | ERR_FATAL;
3420 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003421 }
3422
3423 if (!strncmp(args[1], "rdp-cookie", 10)) {
3424 curproxy->options2 |= PR_O2_RDPC_PRST;
3425
Emeric Brunb982a3d2010-01-04 15:45:53 +01003426 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003427 const char *beg, *end;
3428
3429 beg = args[1] + 11;
3430 end = strchr(beg, ')');
3431
William Lallemanddf1425a2015-04-28 20:17:49 +02003432 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3433 goto out;
3434
Emeric Brun647caf12009-06-30 17:57:00 +02003435 if (!end || end == beg) {
3436 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3437 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003438 err_code |= ERR_ALERT | ERR_FATAL;
3439 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003440 }
3441
3442 free(curproxy->rdp_cookie_name);
3443 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3444 curproxy->rdp_cookie_len = end-beg;
3445 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003446 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003447 free(curproxy->rdp_cookie_name);
3448 curproxy->rdp_cookie_name = strdup("msts");
3449 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3450 }
3451 else { /* syntax */
3452 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3453 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003454 err_code |= ERR_ALERT | ERR_FATAL;
3455 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003456 }
3457 }
3458 else {
3459 Alert("parsing [%s:%d] : unknown persist method.\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 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003465 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreau6db62c52015-08-10 19:04:29 +02003466 Alert("parsing [%s:%d] : '%s' is not supported anymore, please check the documentation.\n", file, linenum, args[0]);
3467 err_code |= ERR_ALERT | ERR_FATAL;
3468 goto out;
3469 }
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02003470 else if (!strcmp(args[0], "load-server-state-from-file")) {
3471 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3472 err_code |= ERR_WARN;
3473 if (!strcmp(args[1], "global")) { /* use the file pointed to by global server-state-file directive */
3474 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_GLOBAL;
3475 }
3476 else if (!strcmp(args[1], "local")) { /* use the server-state-file-name variable to locate the server-state file */
3477 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_LOCAL;
3478 }
3479 else if (!strcmp(args[1], "none")) { /* don't use server-state-file directive for this backend */
3480 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
3481 }
3482 else {
3483 Alert("parsing [%s:%d] : '%s' expects 'global', 'local' or 'none'. Got '%s'\n",
3484 file, linenum, args[0], args[1]);
3485 err_code |= ERR_ALERT | ERR_FATAL;
3486 goto out;
3487 }
3488 }
3489 else if (!strcmp(args[0], "server-state-file-name")) {
3490 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3491 err_code |= ERR_WARN;
3492 if (*(args[1]) == 0) {
3493 Alert("parsing [%s:%d] : '%s' expects 'use-backend-name' or a string. Got no argument\n",
3494 file, linenum, args[0]);
3495 err_code |= ERR_ALERT | ERR_FATAL;
3496 goto out;
3497 }
3498 else if (!strcmp(args[1], "use-backend-name"))
3499 curproxy->server_state_file_name = strdup(curproxy->id);
3500 else
3501 curproxy->server_state_file_name = strdup(args[1]);
3502 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003503 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003504 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003505 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003506
Willy Tarreaubaaee002006-06-26 02:48:02 +02003507 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003508 if (curproxy == &defproxy) {
3509 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3510 err_code |= ERR_ALERT | ERR_FATAL;
3511 goto out;
3512 }
3513
William Lallemand1a748ae2015-05-19 16:37:23 +02003514 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3515 goto out;
3516
Willy Tarreaubaaee002006-06-26 02:48:02 +02003517 if (*(args[4]) == 0) {
3518 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3519 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003520 err_code |= ERR_ALERT | ERR_FATAL;
3521 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003522 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003523 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003524 curproxy->capture_name = strdup(args[2]);
3525 curproxy->capture_namelen = strlen(curproxy->capture_name);
3526 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003527 curproxy->to_log |= LW_COOKIE;
3528 }
3529 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3530 struct cap_hdr *hdr;
3531
3532 if (curproxy == &defproxy) {
3533 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 +02003534 err_code |= ERR_ALERT | ERR_FATAL;
3535 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003536 }
3537
William Lallemand1a748ae2015-05-19 16:37:23 +02003538 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3539 goto out;
3540
Willy Tarreaubaaee002006-06-26 02:48:02 +02003541 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3542 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3543 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003544 err_code |= ERR_ALERT | ERR_FATAL;
3545 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003546 }
3547
3548 hdr = calloc(sizeof(struct cap_hdr), 1);
3549 hdr->next = curproxy->req_cap;
3550 hdr->name = strdup(args[3]);
3551 hdr->namelen = strlen(args[3]);
3552 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003553 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003554 hdr->index = curproxy->nb_req_cap++;
3555 curproxy->req_cap = hdr;
3556 curproxy->to_log |= LW_REQHDR;
3557 }
3558 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3559 struct cap_hdr *hdr;
3560
3561 if (curproxy == &defproxy) {
3562 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 +02003563 err_code |= ERR_ALERT | ERR_FATAL;
3564 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003565 }
3566
William Lallemand1a748ae2015-05-19 16:37:23 +02003567 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3568 goto out;
3569
Willy Tarreaubaaee002006-06-26 02:48:02 +02003570 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3571 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3572 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003573 err_code |= ERR_ALERT | ERR_FATAL;
3574 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003575 }
3576 hdr = calloc(sizeof(struct cap_hdr), 1);
3577 hdr->next = curproxy->rsp_cap;
3578 hdr->name = strdup(args[3]);
3579 hdr->namelen = strlen(args[3]);
3580 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003581 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003582 hdr->index = curproxy->nb_rsp_cap++;
3583 curproxy->rsp_cap = hdr;
3584 curproxy->to_log |= LW_RSPHDR;
3585 }
3586 else {
3587 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3588 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003589 err_code |= ERR_ALERT | ERR_FATAL;
3590 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003591 }
3592 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003593 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003594 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003595 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003596
William Lallemanddf1425a2015-04-28 20:17:49 +02003597 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3598 goto out;
3599
Willy Tarreaubaaee002006-06-26 02:48:02 +02003600 if (*(args[1]) == 0) {
3601 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3602 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003603 err_code |= ERR_ALERT | ERR_FATAL;
3604 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003605 }
3606 curproxy->conn_retries = atol(args[1]);
3607 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003608 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003609 struct act_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003610
3611 if (curproxy == &defproxy) {
3612 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3613 err_code |= ERR_ALERT | ERR_FATAL;
3614 goto out;
3615 }
3616
Willy Tarreau20b0de52012-12-24 15:45:22 +01003617 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003618 !LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003619 (LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3620 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_DENY ||
3621 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REDIR ||
3622 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REQ_AUTH)) {
Willy Tarreau20b0de52012-12-24 15:45:22 +01003623 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 +01003624 file, linenum, args[0]);
3625 err_code |= ERR_WARN;
3626 }
3627
Willy Tarreauff011f22011-01-06 17:51:27 +01003628 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003629
Willy Tarreauff011f22011-01-06 17:51:27 +01003630 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003631 err_code |= ERR_ALERT | ERR_ABORT;
3632 goto out;
3633 }
3634
Willy Tarreau5002f572014-04-23 01:32:02 +02003635 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003636 err_code |= warnif_cond_conflicts(rule->cond,
3637 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3638 file, linenum);
3639
Willy Tarreauff011f22011-01-06 17:51:27 +01003640 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003641 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003642 else if (!strcmp(args[0], "http-response")) { /* response access control */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003643 struct act_rule *rule;
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003644
3645 if (curproxy == &defproxy) {
3646 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3647 err_code |= ERR_ALERT | ERR_FATAL;
3648 goto out;
3649 }
3650
3651 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003652 !LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003653 (LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3654 LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_DENY)) {
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003655 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3656 file, linenum, args[0]);
3657 err_code |= ERR_WARN;
3658 }
3659
3660 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3661
3662 if (!rule) {
3663 err_code |= ERR_ALERT | ERR_ABORT;
3664 goto out;
3665 }
3666
3667 err_code |= warnif_cond_conflicts(rule->cond,
3668 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3669 file, linenum);
3670
3671 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3672 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003673 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3674 /* set the header name and length into the proxy structure */
3675 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3676 err_code |= ERR_WARN;
3677
3678 if (!*args[1]) {
3679 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3680 file, linenum, args[0]);
3681 err_code |= ERR_ALERT | ERR_FATAL;
3682 goto out;
3683 }
3684
3685 /* set the desired header name */
3686 free(curproxy->server_id_hdr_name);
3687 curproxy->server_id_hdr_name = strdup(args[1]);
3688 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3689 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003690 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003691 struct act_rule *rule;
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003692
Willy Tarreaub099aca2008-10-12 17:26:37 +02003693 if (curproxy == &defproxy) {
3694 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003695 err_code |= ERR_ALERT | ERR_FATAL;
3696 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003697 }
3698
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003699 /* emulate "block" using "http-request block". Since these rules are supposed to
3700 * be processed before all http-request rules, we put them into their own list
3701 * and will insert them at the end.
3702 */
3703 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3704 if (!rule) {
3705 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003706 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003707 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003708 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3709 err_code |= warnif_cond_conflicts(rule->cond,
3710 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3711 file, linenum);
3712 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003713
3714 if (!already_warned(WARN_BLOCK_DEPRECATED))
3715 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]);
3716
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003717 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003718 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003719 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003720
Cyril Bonté99ed3272010-01-24 23:29:44 +01003721 if (curproxy == &defproxy) {
3722 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3723 err_code |= ERR_ALERT | ERR_FATAL;
3724 goto out;
3725 }
3726
Willy Tarreaube4653b2015-05-28 15:26:58 +02003727 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003728 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3729 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003730 err_code |= ERR_ALERT | ERR_FATAL;
3731 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003732 }
3733
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003734 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003735 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003736 err_code |= warnif_cond_conflicts(rule->cond,
3737 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3738 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003739 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003740 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003741 struct switching_rule *rule;
3742
Willy Tarreaub099aca2008-10-12 17:26:37 +02003743 if (curproxy == &defproxy) {
3744 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003745 err_code |= ERR_ALERT | ERR_FATAL;
3746 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003747 }
3748
Willy Tarreau55ea7572007-06-17 19:56:27 +02003749 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003750 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003751
3752 if (*(args[1]) == 0) {
3753 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003754 err_code |= ERR_ALERT | ERR_FATAL;
3755 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003756 }
3757
Willy Tarreauf51658d2014-04-23 01:21:56 +02003758 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3759 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3760 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3761 file, linenum, errmsg);
3762 err_code |= ERR_ALERT | ERR_FATAL;
3763 goto out;
3764 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003765
Willy Tarreauf51658d2014-04-23 01:21:56 +02003766 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003767 }
3768
3769 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
3770 rule->cond = cond;
3771 rule->be.name = strdup(args[1]);
3772 LIST_INIT(&rule->list);
3773 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3774 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003775 else if (strcmp(args[0], "use-server") == 0) {
3776 struct server_rule *rule;
3777
3778 if (curproxy == &defproxy) {
3779 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3780 err_code |= ERR_ALERT | ERR_FATAL;
3781 goto out;
3782 }
3783
3784 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3785 err_code |= ERR_WARN;
3786
3787 if (*(args[1]) == 0) {
3788 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3789 err_code |= ERR_ALERT | ERR_FATAL;
3790 goto out;
3791 }
3792
3793 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3794 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3795 file, linenum, args[0]);
3796 err_code |= ERR_ALERT | ERR_FATAL;
3797 goto out;
3798 }
3799
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003800 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3801 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3802 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003803 err_code |= ERR_ALERT | ERR_FATAL;
3804 goto out;
3805 }
3806
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003807 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003808
3809 rule = (struct server_rule *)calloc(1, sizeof(*rule));
3810 rule->cond = cond;
3811 rule->srv.name = strdup(args[1]);
3812 LIST_INIT(&rule->list);
3813 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3814 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3815 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003816 else if ((!strcmp(args[0], "force-persist")) ||
3817 (!strcmp(args[0], "ignore-persist"))) {
3818 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003819
3820 if (curproxy == &defproxy) {
3821 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3822 err_code |= ERR_ALERT | ERR_FATAL;
3823 goto out;
3824 }
3825
3826 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3827 err_code |= ERR_WARN;
3828
Willy Tarreauef6494c2010-01-28 17:12:36 +01003829 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003830 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3831 file, linenum, args[0]);
3832 err_code |= ERR_ALERT | ERR_FATAL;
3833 goto out;
3834 }
3835
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003836 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3837 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3838 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003839 err_code |= ERR_ALERT | ERR_FATAL;
3840 goto out;
3841 }
3842
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003843 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3844 * where force-persist is applied.
3845 */
3846 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003847
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003848 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003849 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003850 if (!strcmp(args[0], "force-persist")) {
3851 rule->type = PERSIST_TYPE_FORCE;
3852 } else {
3853 rule->type = PERSIST_TYPE_IGNORE;
3854 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003855 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003856 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003857 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003858 else if (!strcmp(args[0], "stick-table")) {
3859 int myidx = 1;
Willy Tarreaue45288c2015-05-26 10:49:46 +02003860 struct proxy *other;
3861
Willy Tarreaue2dc1fa2015-05-26 12:08:07 +02003862 other = proxy_tbl_by_name(curproxy->id);
Willy Tarreaue45288c2015-05-26 10:49:46 +02003863 if (other) {
3864 Alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
3865 file, linenum, curproxy->id, proxy_type_str(other), other->id, other->conf.file, other->conf.line);
3866 err_code |= ERR_ALERT | ERR_FATAL;
3867 goto out;
3868 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003869
Emeric Brun32da3c42010-09-23 18:39:19 +02003870 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003871 curproxy->table.type = (unsigned int)-1;
3872 while (*args[myidx]) {
3873 const char *err;
3874
3875 if (strcmp(args[myidx], "size") == 0) {
3876 myidx++;
3877 if (!*(args[myidx])) {
3878 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3879 file, linenum, args[myidx-1]);
3880 err_code |= ERR_ALERT | ERR_FATAL;
3881 goto out;
3882 }
3883 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3884 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3885 file, linenum, *err, args[myidx-1]);
3886 err_code |= ERR_ALERT | ERR_FATAL;
3887 goto out;
3888 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003889 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003890 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003891 else if (strcmp(args[myidx], "peers") == 0) {
3892 myidx++;
Godbach50523162013-12-11 19:48:57 +08003893 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003894 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3895 file, linenum, args[myidx-1]);
3896 err_code |= ERR_ALERT | ERR_FATAL;
3897 goto out;
Godbach50523162013-12-11 19:48:57 +08003898 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003899 curproxy->table.peers.name = strdup(args[myidx++]);
3900 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003901 else if (strcmp(args[myidx], "expire") == 0) {
3902 myidx++;
3903 if (!*(args[myidx])) {
3904 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3905 file, linenum, args[myidx-1]);
3906 err_code |= ERR_ALERT | ERR_FATAL;
3907 goto out;
3908 }
3909 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3910 if (err) {
3911 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3912 file, linenum, *err, args[myidx-1]);
3913 err_code |= ERR_ALERT | ERR_FATAL;
3914 goto out;
3915 }
3916 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003917 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003918 }
3919 else if (strcmp(args[myidx], "nopurge") == 0) {
3920 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003921 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003922 }
3923 else if (strcmp(args[myidx], "type") == 0) {
3924 myidx++;
3925 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3926 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3927 file, linenum, args[myidx]);
3928 err_code |= ERR_ALERT | ERR_FATAL;
3929 goto out;
3930 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003931 /* myidx already points to next arg */
3932 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003933 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003934 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003935 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003936
3937 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003938 nw = args[myidx];
3939 while (*nw) {
3940 /* the "store" keyword supports a comma-separated list */
3941 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003942 sa = NULL; /* store arg */
3943 while (*nw && *nw != ',') {
3944 if (*nw == '(') {
3945 *nw = 0;
3946 sa = ++nw;
3947 while (*nw != ')') {
3948 if (!*nw) {
3949 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3950 file, linenum, args[0], cw);
3951 err_code |= ERR_ALERT | ERR_FATAL;
3952 goto out;
3953 }
3954 nw++;
3955 }
3956 *nw = '\0';
3957 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003958 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003959 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003960 if (*nw)
3961 *nw++ = '\0';
3962 type = stktable_get_data_type(cw);
3963 if (type < 0) {
3964 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3965 file, linenum, args[0], cw);
3966 err_code |= ERR_ALERT | ERR_FATAL;
3967 goto out;
3968 }
Willy Tarreauac782882010-06-20 10:41:54 +02003969
3970 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3971 switch (err) {
3972 case PE_NONE: break;
3973 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003974 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3975 file, linenum, args[0], cw);
3976 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003977 break;
3978
3979 case PE_ARG_MISSING:
3980 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3981 file, linenum, args[0], cw);
3982 err_code |= ERR_ALERT | ERR_FATAL;
3983 goto out;
3984
3985 case PE_ARG_NOT_USED:
3986 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3987 file, linenum, args[0], cw);
3988 err_code |= ERR_ALERT | ERR_FATAL;
3989 goto out;
3990
3991 default:
3992 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3993 file, linenum, args[0], cw);
3994 err_code |= ERR_ALERT | ERR_FATAL;
3995 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003996 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003997 }
3998 myidx++;
3999 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004000 else {
4001 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
4002 file, linenum, args[myidx]);
4003 err_code |= ERR_ALERT | ERR_FATAL;
4004 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004005 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004006 }
4007
4008 if (!curproxy->table.size) {
4009 Alert("parsing [%s:%d] : stick-table: missing size.\n",
4010 file, linenum);
4011 err_code |= ERR_ALERT | ERR_FATAL;
4012 goto out;
4013 }
4014
4015 if (curproxy->table.type == (unsigned int)-1) {
4016 Alert("parsing [%s:%d] : stick-table: missing type.\n",
4017 file, linenum);
4018 err_code |= ERR_ALERT | ERR_FATAL;
4019 goto out;
4020 }
4021 }
4022 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004023 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02004024 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004025 int myidx = 0;
4026 const char *name = NULL;
4027 int flags;
4028
4029 if (curproxy == &defproxy) {
4030 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4031 err_code |= ERR_ALERT | ERR_FATAL;
4032 goto out;
4033 }
4034
4035 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
4036 err_code |= ERR_WARN;
4037 goto out;
4038 }
4039
4040 myidx++;
4041 if ((strcmp(args[myidx], "store") == 0) ||
4042 (strcmp(args[myidx], "store-request") == 0)) {
4043 myidx++;
4044 flags = STK_IS_STORE;
4045 }
4046 else if (strcmp(args[myidx], "store-response") == 0) {
4047 myidx++;
4048 flags = STK_IS_STORE | STK_ON_RSP;
4049 }
4050 else if (strcmp(args[myidx], "match") == 0) {
4051 myidx++;
4052 flags = STK_IS_MATCH;
4053 }
4054 else if (strcmp(args[myidx], "on") == 0) {
4055 myidx++;
4056 flags = STK_IS_MATCH | STK_IS_STORE;
4057 }
4058 else {
4059 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
4060 err_code |= ERR_ALERT | ERR_FATAL;
4061 goto out;
4062 }
4063
4064 if (*(args[myidx]) == 0) {
4065 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
4066 err_code |= ERR_ALERT | ERR_FATAL;
4067 goto out;
4068 }
4069
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004070 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01004071 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004072 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01004073 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004074 err_code |= ERR_ALERT | ERR_FATAL;
4075 goto out;
4076 }
4077
4078 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01004079 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
4080 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
4081 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004082 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004083 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004084 goto out;
4085 }
4086 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01004087 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
4088 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
4089 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004090 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004091 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004092 goto out;
4093 }
4094 }
4095
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004096 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01004097 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004098
Emeric Brunb982a3d2010-01-04 15:45:53 +01004099 if (strcmp(args[myidx], "table") == 0) {
4100 myidx++;
4101 name = args[myidx++];
4102 }
4103
Willy Tarreauef6494c2010-01-28 17:12:36 +01004104 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004105 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
4106 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
4107 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004108 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004109 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004110 goto out;
4111 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004112 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01004113 else if (*(args[myidx])) {
4114 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
4115 file, linenum, args[0], args[myidx]);
4116 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004117 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01004118 goto out;
4119 }
Emeric Brun97679e72010-09-23 17:56:44 +02004120 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004121 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02004122 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004123 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01004124
Emeric Brunb982a3d2010-01-04 15:45:53 +01004125 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
4126 rule->cond = cond;
4127 rule->expr = expr;
4128 rule->flags = flags;
4129 rule->table.name = name ? strdup(name) : NULL;
4130 LIST_INIT(&rule->list);
4131 if (flags & STK_ON_RSP)
4132 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
4133 else
4134 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
4135 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004136 else if (!strcmp(args[0], "stats")) {
4137 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
4138 curproxy->uri_auth = NULL; /* we must detach from the default config */
4139
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004140 if (!*args[1]) {
4141 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02004142 } else if (!strcmp(args[1], "admin")) {
4143 struct stats_admin_rule *rule;
4144
4145 if (curproxy == &defproxy) {
4146 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
4147 err_code |= ERR_ALERT | ERR_FATAL;
4148 goto out;
4149 }
4150
4151 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4152 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4153 err_code |= ERR_ALERT | ERR_ABORT;
4154 goto out;
4155 }
4156
4157 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4158 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4159 file, linenum, args[0], args[1]);
4160 err_code |= ERR_ALERT | ERR_FATAL;
4161 goto out;
4162 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004163 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4164 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
4165 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02004166 err_code |= ERR_ALERT | ERR_FATAL;
4167 goto out;
4168 }
4169
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004170 err_code |= warnif_cond_conflicts(cond,
4171 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4172 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02004173
4174 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
4175 rule->cond = cond;
4176 LIST_INIT(&rule->list);
4177 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004178 } else if (!strcmp(args[1], "uri")) {
4179 if (*(args[2]) == 0) {
4180 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004181 err_code |= ERR_ALERT | ERR_FATAL;
4182 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004183 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
4184 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004185 err_code |= ERR_ALERT | ERR_ABORT;
4186 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004187 }
4188 } else if (!strcmp(args[1], "realm")) {
4189 if (*(args[2]) == 0) {
4190 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004191 err_code |= ERR_ALERT | ERR_FATAL;
4192 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004193 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
4194 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004195 err_code |= ERR_ALERT | ERR_ABORT;
4196 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004197 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02004198 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004199 unsigned interval;
4200
4201 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
4202 if (err) {
4203 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
4204 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004205 err_code |= ERR_ALERT | ERR_FATAL;
4206 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004207 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
4208 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004209 err_code |= ERR_ALERT | ERR_ABORT;
4210 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004211 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004212 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004213 struct act_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004214
4215 if (curproxy == &defproxy) {
4216 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4217 err_code |= ERR_ALERT | ERR_FATAL;
4218 goto out;
4219 }
4220
4221 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4222 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4223 err_code |= ERR_ALERT | ERR_ABORT;
4224 goto out;
4225 }
4226
Willy Tarreauff011f22011-01-06 17:51:27 +01004227 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004228 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct act_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004229 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
4230 file, linenum, args[0]);
4231 err_code |= ERR_WARN;
4232 }
4233
Willy Tarreauff011f22011-01-06 17:51:27 +01004234 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004235
Willy Tarreauff011f22011-01-06 17:51:27 +01004236 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004237 err_code |= ERR_ALERT | ERR_ABORT;
4238 goto out;
4239 }
4240
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004241 err_code |= warnif_cond_conflicts(rule->cond,
4242 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4243 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01004244 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004245
Willy Tarreaubaaee002006-06-26 02:48:02 +02004246 } else if (!strcmp(args[1], "auth")) {
4247 if (*(args[2]) == 0) {
4248 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004249 err_code |= ERR_ALERT | ERR_FATAL;
4250 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004251 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
4252 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004253 err_code |= ERR_ALERT | ERR_ABORT;
4254 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004255 }
4256 } else if (!strcmp(args[1], "scope")) {
4257 if (*(args[2]) == 0) {
4258 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004259 err_code |= ERR_ALERT | ERR_FATAL;
4260 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004261 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
4262 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004263 err_code |= ERR_ALERT | ERR_ABORT;
4264 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004265 }
4266 } else if (!strcmp(args[1], "enable")) {
4267 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4268 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004269 err_code |= ERR_ALERT | ERR_ABORT;
4270 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004271 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004272 } else if (!strcmp(args[1], "hide-version")) {
4273 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
4274 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004275 err_code |= ERR_ALERT | ERR_ABORT;
4276 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004277 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01004278 } else if (!strcmp(args[1], "show-legends")) {
4279 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
4280 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4281 err_code |= ERR_ALERT | ERR_ABORT;
4282 goto out;
4283 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004284 } else if (!strcmp(args[1], "show-node")) {
4285
4286 if (*args[2]) {
4287 int i;
4288 char c;
4289
4290 for (i=0; args[2][i]; i++) {
4291 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01004292 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
4293 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004294 break;
4295 }
4296
4297 if (!i || args[2][i]) {
4298 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
4299 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
4300 file, linenum, args[0], args[1]);
4301 err_code |= ERR_ALERT | ERR_FATAL;
4302 goto out;
4303 }
4304 }
4305
4306 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
4307 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4308 err_code |= ERR_ALERT | ERR_ABORT;
4309 goto out;
4310 }
4311 } else if (!strcmp(args[1], "show-desc")) {
4312 char *desc = NULL;
4313
4314 if (*args[2]) {
4315 int i, len=0;
4316 char *d;
4317
Willy Tarreau348acfe2014-04-14 15:00:39 +02004318 for (i = 2; *args[i]; i++)
4319 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004320
4321 desc = d = (char *)calloc(1, len);
4322
Willy Tarreau348acfe2014-04-14 15:00:39 +02004323 d += snprintf(d, desc + len - d, "%s", args[2]);
4324 for (i = 3; *args[i]; i++)
4325 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004326 }
4327
4328 if (!*args[2] && !global.desc)
4329 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
4330 file, linenum, args[1]);
4331 else {
4332 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
4333 free(desc);
4334 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4335 err_code |= ERR_ALERT | ERR_ABORT;
4336 goto out;
4337 }
4338 free(desc);
4339 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004340 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004341stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02004342 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 +01004343 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004344 err_code |= ERR_ALERT | ERR_FATAL;
4345 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004346 }
4347 }
4348 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004349 int optnum;
4350
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004351 if (*(args[1]) == '\0') {
4352 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
4353 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004354 err_code |= ERR_ALERT | ERR_FATAL;
4355 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004356 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01004357
4358 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
4359 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004360 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
4361 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4362 file, linenum, cfg_opts[optnum].name);
4363 err_code |= ERR_ALERT | ERR_FATAL;
4364 goto out;
4365 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004366 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4367 goto out;
4368
Willy Tarreau93893792009-07-23 13:19:11 +02004369 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
4370 err_code |= ERR_WARN;
4371 goto out;
4372 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004373
Willy Tarreau3842f002009-06-14 11:39:52 +02004374 curproxy->no_options &= ~cfg_opts[optnum].val;
4375 curproxy->options &= ~cfg_opts[optnum].val;
4376
4377 switch (kwm) {
4378 case KWM_STD:
4379 curproxy->options |= cfg_opts[optnum].val;
4380 break;
4381 case KWM_NO:
4382 curproxy->no_options |= cfg_opts[optnum].val;
4383 break;
4384 case KWM_DEF: /* already cleared */
4385 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004386 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004387
Willy Tarreau93893792009-07-23 13:19:11 +02004388 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004389 }
4390 }
4391
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004392 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
4393 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004394 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
4395 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4396 file, linenum, cfg_opts2[optnum].name);
4397 err_code |= ERR_ALERT | ERR_FATAL;
4398 goto out;
4399 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004400 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4401 goto out;
Willy Tarreau93893792009-07-23 13:19:11 +02004402 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4403 err_code |= ERR_WARN;
4404 goto out;
4405 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004406
Willy Tarreau3842f002009-06-14 11:39:52 +02004407 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4408 curproxy->options2 &= ~cfg_opts2[optnum].val;
4409
4410 switch (kwm) {
4411 case KWM_STD:
4412 curproxy->options2 |= cfg_opts2[optnum].val;
4413 break;
4414 case KWM_NO:
4415 curproxy->no_options2 |= cfg_opts2[optnum].val;
4416 break;
4417 case KWM_DEF: /* already cleared */
4418 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004419 }
Willy Tarreau93893792009-07-23 13:19:11 +02004420 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004421 }
4422 }
4423
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004424 /* HTTP options override each other. They can be cancelled using
4425 * "no option xxx" which only switches to default mode if the mode
4426 * was this one (useful for cancelling options set in defaults
4427 * sections).
4428 */
4429 if (strcmp(args[1], "httpclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004430 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4431 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004432 if (kwm == KWM_STD) {
4433 curproxy->options &= ~PR_O_HTTP_MODE;
4434 curproxy->options |= PR_O_HTTP_PCL;
4435 goto out;
4436 }
4437 else if (kwm == KWM_NO) {
4438 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4439 curproxy->options &= ~PR_O_HTTP_MODE;
4440 goto out;
4441 }
4442 }
4443 else if (strcmp(args[1], "forceclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004444 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4445 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004446 if (kwm == KWM_STD) {
4447 curproxy->options &= ~PR_O_HTTP_MODE;
4448 curproxy->options |= PR_O_HTTP_FCL;
4449 goto out;
4450 }
4451 else if (kwm == KWM_NO) {
4452 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4453 curproxy->options &= ~PR_O_HTTP_MODE;
4454 goto out;
4455 }
4456 }
4457 else if (strcmp(args[1], "http-server-close") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004458 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4459 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004460 if (kwm == KWM_STD) {
4461 curproxy->options &= ~PR_O_HTTP_MODE;
4462 curproxy->options |= PR_O_HTTP_SCL;
4463 goto out;
4464 }
4465 else if (kwm == KWM_NO) {
4466 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4467 curproxy->options &= ~PR_O_HTTP_MODE;
4468 goto out;
4469 }
4470 }
4471 else if (strcmp(args[1], "http-keep-alive") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004472 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4473 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004474 if (kwm == KWM_STD) {
4475 curproxy->options &= ~PR_O_HTTP_MODE;
4476 curproxy->options |= PR_O_HTTP_KAL;
4477 goto out;
4478 }
4479 else if (kwm == KWM_NO) {
4480 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4481 curproxy->options &= ~PR_O_HTTP_MODE;
4482 goto out;
4483 }
4484 }
4485 else if (strcmp(args[1], "http-tunnel") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004486 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4487 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004488 if (kwm == KWM_STD) {
4489 curproxy->options &= ~PR_O_HTTP_MODE;
4490 curproxy->options |= PR_O_HTTP_TUN;
4491 goto out;
4492 }
4493 else if (kwm == KWM_NO) {
4494 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4495 curproxy->options &= ~PR_O_HTTP_MODE;
4496 goto out;
4497 }
4498 }
4499
Joseph Lynch726ab712015-05-11 23:25:34 -07004500 /* Redispatch can take an integer argument that control when the
4501 * resispatch occurs. All values are relative to the retries option.
4502 * This can be cancelled using "no option xxx".
4503 */
4504 if (strcmp(args[1], "redispatch") == 0) {
4505 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
4506 err_code |= ERR_WARN;
4507 goto out;
4508 }
4509
4510 curproxy->no_options &= ~PR_O_REDISP;
4511 curproxy->options &= ~PR_O_REDISP;
4512
4513 switch (kwm) {
4514 case KWM_STD:
4515 curproxy->options |= PR_O_REDISP;
4516 curproxy->redispatch_after = -1;
4517 if(*args[2]) {
4518 curproxy->redispatch_after = atol(args[2]);
4519 }
4520 break;
4521 case KWM_NO:
4522 curproxy->no_options |= PR_O_REDISP;
4523 curproxy->redispatch_after = 0;
4524 break;
4525 case KWM_DEF: /* already cleared */
4526 break;
4527 }
4528 goto out;
4529 }
4530
Willy Tarreau3842f002009-06-14 11:39:52 +02004531 if (kwm != KWM_STD) {
4532 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004533 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004534 err_code |= ERR_ALERT | ERR_FATAL;
4535 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004536 }
4537
Emeric Brun3a058f32009-06-30 18:26:00 +02004538 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004539 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004540 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004541 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004542 if (*(args[2]) != '\0') {
4543 if (!strcmp(args[2], "clf")) {
4544 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004545 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004546 } else {
William Lallemand77063bc2015-05-28 18:02:48 +02004547 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004548 err_code |= ERR_ALERT | ERR_FATAL;
4549 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004550 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004551 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
4552 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004553 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004554 if (curproxy->conf.logformat_string != default_http_log_format &&
4555 curproxy->conf.logformat_string != default_tcp_log_format &&
4556 curproxy->conf.logformat_string != clf_http_log_format)
4557 free(curproxy->conf.logformat_string);
4558 curproxy->conf.logformat_string = logformat;
4559
4560 free(curproxy->conf.lfs_file);
4561 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4562 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004563 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004564 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004565 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004566 if (curproxy->conf.logformat_string != default_http_log_format &&
4567 curproxy->conf.logformat_string != default_tcp_log_format &&
4568 curproxy->conf.logformat_string != clf_http_log_format)
4569 free(curproxy->conf.logformat_string);
4570 curproxy->conf.logformat_string = default_tcp_log_format;
4571
4572 free(curproxy->conf.lfs_file);
4573 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4574 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemanddf1425a2015-04-28 20:17:49 +02004575
4576 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4577 goto out;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004578 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004579 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004580 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004581 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004582 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004583
William Lallemanddf1425a2015-04-28 20:17:49 +02004584 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4585 goto out;
4586
Willy Tarreau13943ab2006-12-31 00:24:10 +01004587 if (curproxy->cap & PR_CAP_FE)
4588 curproxy->options |= PR_O_TCP_CLI_KA;
4589 if (curproxy->cap & PR_CAP_BE)
4590 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004591 }
4592 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004593 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004594 err_code |= ERR_WARN;
4595
Willy Tarreaubaaee002006-06-26 02:48:02 +02004596 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004597 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004598 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004599 curproxy->options2 &= ~PR_O2_CHK_ANY;
4600 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004601 if (!*args[2]) { /* no argument */
4602 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4603 curproxy->check_len = strlen(DEF_CHECK_REQ);
4604 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004605 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004606 curproxy->check_req = (char *)malloc(reqlen);
4607 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004608 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004609 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004610 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004611 if (*args[4])
4612 reqlen += strlen(args[4]);
4613 else
4614 reqlen += strlen("HTTP/1.0");
4615
4616 curproxy->check_req = (char *)malloc(reqlen);
4617 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004618 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004619 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004620 if (alertif_too_many_args_idx(3, 1, file, linenum, args, &err_code))
4621 goto out;
Willy Tarreauf3c69202006-07-09 16:42:34 +02004622 }
4623 else if (!strcmp(args[1], "ssl-hello-chk")) {
4624 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004625 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004626 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004627
Willy Tarreaua534fea2008-08-03 12:19:50 +02004628 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004629 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004630 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004631 curproxy->options2 |= PR_O2_SSL3_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004632
4633 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4634 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004635 }
Willy Tarreau23677902007-05-08 23:50:35 +02004636 else if (!strcmp(args[1], "smtpchk")) {
4637 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004638 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004639 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004640 curproxy->options2 &= ~PR_O2_CHK_ANY;
4641 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004642
4643 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4644 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4645 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4646 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4647 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4648 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
4649 curproxy->check_req = (char *)malloc(reqlen);
4650 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4651 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4652 } else {
4653 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4654 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4655 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4656 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4657 }
4658 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004659 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4660 goto out;
Willy Tarreau23677902007-05-08 23:50:35 +02004661 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004662 else if (!strcmp(args[1], "pgsql-check")) {
4663 /* use PostgreSQL request to check servers' health */
4664 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4665 err_code |= ERR_WARN;
4666
4667 free(curproxy->check_req);
4668 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004669 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004670 curproxy->options2 |= PR_O2_PGSQL_CHK;
4671
4672 if (*(args[2])) {
4673 int cur_arg = 2;
4674
4675 while (*(args[cur_arg])) {
4676 if (strcmp(args[cur_arg], "user") == 0) {
4677 char * packet;
4678 uint32_t packet_len;
4679 uint32_t pv;
4680
4681 /* suboption header - needs additional argument for it */
4682 if (*(args[cur_arg+1]) == 0) {
4683 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4684 file, linenum, args[0], args[1], args[cur_arg]);
4685 err_code |= ERR_ALERT | ERR_FATAL;
4686 goto out;
4687 }
4688
4689 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4690 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4691 pv = htonl(0x30000); /* protocol version 3.0 */
4692
4693 packet = (char*) calloc(1, packet_len);
4694
4695 memcpy(packet + 4, &pv, 4);
4696
4697 /* copy "user" */
4698 memcpy(packet + 8, "user", 4);
4699
4700 /* copy username */
4701 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4702
4703 free(curproxy->check_req);
4704 curproxy->check_req = packet;
4705 curproxy->check_len = packet_len;
4706
4707 packet_len = htonl(packet_len);
4708 memcpy(packet, &packet_len, 4);
4709 cur_arg += 2;
4710 } else {
4711 /* unknown suboption - catchall */
4712 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4713 file, linenum, args[0], args[1]);
4714 err_code |= ERR_ALERT | ERR_FATAL;
4715 goto out;
4716 }
4717 } /* end while loop */
4718 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004719 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4720 goto out;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004721 }
4722
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004723 else if (!strcmp(args[1], "redis-check")) {
4724 /* use REDIS PING request to check servers' health */
4725 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4726 err_code |= ERR_WARN;
4727
4728 free(curproxy->check_req);
4729 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004730 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004731 curproxy->options2 |= PR_O2_REDIS_CHK;
4732
4733 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
4734 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4735 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004736
4737 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4738 goto out;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004739 }
4740
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004741 else if (!strcmp(args[1], "mysql-check")) {
4742 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004743 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4744 err_code |= ERR_WARN;
4745
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004746 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004747 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004748 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004749 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004750
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004751 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004752 * const char mysql40_client_auth_pkt[] = {
4753 * "\x0e\x00\x00" // packet length
4754 * "\x01" // packet number
4755 * "\x00\x00" // client capabilities
4756 * "\x00\x00\x01" // max packet
4757 * "haproxy\x00" // username (null terminated string)
4758 * "\x00" // filler (always 0x00)
4759 * "\x01\x00\x00" // packet length
4760 * "\x00" // packet number
4761 * "\x01" // COM_QUIT command
4762 * };
4763 */
4764
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004765 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4766 * const char mysql41_client_auth_pkt[] = {
4767 * "\x0e\x00\x00\" // packet length
4768 * "\x01" // packet number
4769 * "\x00\x00\x00\x00" // client capabilities
4770 * "\x00\x00\x00\x01" // max packet
4771 * "\x21" // character set (UTF-8)
4772 * char[23] // All zeroes
4773 * "haproxy\x00" // username (null terminated string)
4774 * "\x00" // filler (always 0x00)
4775 * "\x01\x00\x00" // packet length
4776 * "\x00" // packet number
4777 * "\x01" // COM_QUIT command
4778 * };
4779 */
4780
4781
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004782 if (*(args[2])) {
4783 int cur_arg = 2;
4784
4785 while (*(args[cur_arg])) {
4786 if (strcmp(args[cur_arg], "user") == 0) {
4787 char *mysqluser;
4788 int packetlen, reqlen, userlen;
4789
4790 /* suboption header - needs additional argument for it */
4791 if (*(args[cur_arg+1]) == 0) {
4792 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4793 file, linenum, args[0], args[1], args[cur_arg]);
4794 err_code |= ERR_ALERT | ERR_FATAL;
4795 goto out;
4796 }
4797 mysqluser = args[cur_arg + 1];
4798 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004799
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004800 if (*(args[cur_arg+2])) {
4801 if (!strcmp(args[cur_arg+2], "post-41")) {
4802 packetlen = userlen + 7 + 27;
4803 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004804
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004805 free(curproxy->check_req);
4806 curproxy->check_req = (char *)calloc(1, reqlen);
4807 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004808
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004809 snprintf(curproxy->check_req, 4, "%c%c%c",
4810 ((unsigned char) packetlen & 0xff),
4811 ((unsigned char) (packetlen >> 8) & 0xff),
4812 ((unsigned char) (packetlen >> 16) & 0xff));
4813
4814 curproxy->check_req[3] = 1;
4815 curproxy->check_req[5] = 130;
4816 curproxy->check_req[11] = 1;
4817 curproxy->check_req[12] = 33;
4818 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4819 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4820 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4821 cur_arg += 3;
4822 } else {
4823 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4824 err_code |= ERR_ALERT | ERR_FATAL;
4825 goto out;
4826 }
4827 } else {
4828 packetlen = userlen + 7;
4829 reqlen = packetlen + 9;
4830
4831 free(curproxy->check_req);
4832 curproxy->check_req = (char *)calloc(1, reqlen);
4833 curproxy->check_len = reqlen;
4834
4835 snprintf(curproxy->check_req, 4, "%c%c%c",
4836 ((unsigned char) packetlen & 0xff),
4837 ((unsigned char) (packetlen >> 8) & 0xff),
4838 ((unsigned char) (packetlen >> 16) & 0xff));
4839
4840 curproxy->check_req[3] = 1;
4841 curproxy->check_req[5] = 128;
4842 curproxy->check_req[8] = 1;
4843 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4844 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4845 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4846 cur_arg += 2;
4847 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004848 } else {
4849 /* unknown suboption - catchall */
4850 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4851 file, linenum, args[0], args[1]);
4852 err_code |= ERR_ALERT | ERR_FATAL;
4853 goto out;
4854 }
4855 } /* end while loop */
4856 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004857 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004858 else if (!strcmp(args[1], "ldap-check")) {
4859 /* use LDAP request to check servers' health */
4860 free(curproxy->check_req);
4861 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004862 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004863 curproxy->options2 |= PR_O2_LDAP_CHK;
4864
4865 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
4866 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
4867 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004868 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4869 goto out;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004870 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004871 else if (!strcmp(args[1], "tcp-check")) {
4872 /* use raw TCPCHK send/expect to check servers' health */
4873 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4874 err_code |= ERR_WARN;
4875
4876 free(curproxy->check_req);
4877 curproxy->check_req = NULL;
4878 curproxy->options2 &= ~PR_O2_CHK_ANY;
4879 curproxy->options2 |= PR_O2_TCPCHK_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004880 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4881 goto out;
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004882 }
Simon Horman98637e52014-06-20 12:30:16 +09004883 else if (!strcmp(args[1], "external-check")) {
4884 /* excute an external command to check servers' health */
4885 free(curproxy->check_req);
4886 curproxy->check_req = NULL;
4887 curproxy->options2 &= ~PR_O2_CHK_ANY;
4888 curproxy->options2 |= PR_O2_EXT_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004889 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4890 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09004891 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004892 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004893 int cur_arg;
4894
4895 /* insert x-forwarded-for field, but not for the IP address listed as an except.
4896 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004897 */
Ross Westaf72a1d2008-08-03 10:51:45 +02004898
Willy Tarreau87cf5142011-08-19 22:57:24 +02004899 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02004900
4901 free(curproxy->fwdfor_hdr_name);
4902 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
4903 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
4904
4905 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
4906 cur_arg = 2;
4907 while (*(args[cur_arg])) {
4908 if (!strcmp(args[cur_arg], "except")) {
4909 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004910 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004911 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4912 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004913 err_code |= ERR_ALERT | ERR_FATAL;
4914 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004915 }
4916 /* flush useless bits */
4917 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02004918 cur_arg += 2;
4919 } else if (!strcmp(args[cur_arg], "header")) {
4920 /* suboption header - needs additional argument for it */
4921 if (*(args[cur_arg+1]) == 0) {
4922 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4923 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004924 err_code |= ERR_ALERT | ERR_FATAL;
4925 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02004926 }
4927 free(curproxy->fwdfor_hdr_name);
4928 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
4929 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
4930 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02004931 } else if (!strcmp(args[cur_arg], "if-none")) {
4932 curproxy->options &= ~PR_O_FF_ALWAYS;
4933 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004934 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02004935 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02004936 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02004937 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004938 err_code |= ERR_ALERT | ERR_FATAL;
4939 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004940 }
Ross Westaf72a1d2008-08-03 10:51:45 +02004941 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004942 }
Maik Broemme2850cb42009-04-17 18:53:21 +02004943 else if (!strcmp(args[1], "originalto")) {
4944 int cur_arg;
4945
4946 /* insert x-original-to field, but not for the IP address listed as an except.
4947 * set default options (ie: bitfield, header name, etc)
4948 */
4949
4950 curproxy->options |= PR_O_ORGTO;
4951
4952 free(curproxy->orgto_hdr_name);
4953 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
4954 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
4955
Willy Tarreau87cf5142011-08-19 22:57:24 +02004956 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02004957 cur_arg = 2;
4958 while (*(args[cur_arg])) {
4959 if (!strcmp(args[cur_arg], "except")) {
4960 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004961 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_to, &curproxy->except_mask_to)) {
Maik Broemme2850cb42009-04-17 18:53:21 +02004962 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4963 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004964 err_code |= ERR_ALERT | ERR_FATAL;
4965 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004966 }
4967 /* flush useless bits */
4968 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
4969 cur_arg += 2;
4970 } else if (!strcmp(args[cur_arg], "header")) {
4971 /* suboption header - needs additional argument for it */
4972 if (*(args[cur_arg+1]) == 0) {
4973 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4974 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004975 err_code |= ERR_ALERT | ERR_FATAL;
4976 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004977 }
4978 free(curproxy->orgto_hdr_name);
4979 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
4980 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
4981 cur_arg += 2;
4982 } else {
4983 /* unknown suboption - catchall */
4984 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
4985 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004986 err_code |= ERR_ALERT | ERR_FATAL;
4987 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004988 }
4989 } /* end while loop */
4990 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004991 else {
4992 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004993 err_code |= ERR_ALERT | ERR_FATAL;
4994 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004995 }
Willy Tarreau93893792009-07-23 13:19:11 +02004996 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004997 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004998 else if (!strcmp(args[0], "default_backend")) {
4999 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005000 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005001
5002 if (*(args[1]) == 0) {
5003 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005004 err_code |= ERR_ALERT | ERR_FATAL;
5005 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005006 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005007 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005008 curproxy->defbe.name = strdup(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005009
5010 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5011 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005012 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005013 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01005014 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005015 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005016
Willy Tarreaua3c504c2014-04-28 22:37:32 +02005017 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
5018 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 +01005019 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005020 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005021 /* enable reconnections to dispatch */
5022 curproxy->options |= PR_O_REDISP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005023
5024 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5025 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005026 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005027 else if (!strcmp(args[0], "http-reuse")) {
5028 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5029 err_code |= ERR_WARN;
5030
5031 if (strcmp(args[1], "never") == 0) {
5032 /* enable a graceful server shutdown on an HTTP 404 response */
5033 curproxy->options &= ~PR_O_REUSE_MASK;
5034 curproxy->options |= PR_O_REUSE_NEVR;
5035 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5036 goto out;
5037 }
Willy Tarreau161d45f2015-08-05 16:02:46 +02005038 else if (strcmp(args[1], "safe") == 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_SAFE;
5042 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5043 goto out;
5044 }
Willy Tarreau449d74a2015-08-05 17:16:33 +02005045 else if (strcmp(args[1], "aggressive") == 0) {
5046 curproxy->options &= ~PR_O_REUSE_MASK;
5047 curproxy->options |= PR_O_REUSE_AGGR;
5048 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5049 goto out;
5050 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005051 else if (strcmp(args[1], "always") == 0) {
5052 /* enable a graceful server shutdown on an HTTP 404 response */
5053 curproxy->options &= ~PR_O_REUSE_MASK;
5054 curproxy->options |= PR_O_REUSE_ALWS;
5055 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5056 goto out;
5057 }
5058 else {
Willy Tarreau449d74a2015-08-05 17:16:33 +02005059 Alert("parsing [%s:%d] : '%s' only supports 'never', 'safe', 'aggressive', 'always'.\n", file, linenum, args[0]);
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005060 err_code |= ERR_ALERT | ERR_FATAL;
5061 goto out;
5062 }
5063 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005064 else if (!strcmp(args[0], "http-check")) {
5065 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005066 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01005067
5068 if (strcmp(args[1], "disable-on-404") == 0) {
5069 /* enable a graceful server shutdown on an HTTP 404 response */
5070 curproxy->options |= PR_O_DISABLE404;
William Lallemanddf1425a2015-04-28 20:17:49 +02005071 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5072 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005073 }
Willy Tarreauef781042010-01-27 11:53:01 +01005074 else if (strcmp(args[1], "send-state") == 0) {
5075 /* enable emission of the apparent state of a server in HTTP checks */
5076 curproxy->options2 |= PR_O2_CHK_SNDST;
William Lallemanddf1425a2015-04-28 20:17:49 +02005077 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5078 goto out;
Willy Tarreauef781042010-01-27 11:53:01 +01005079 }
Willy Tarreaubd741542010-03-16 18:46:54 +01005080 else if (strcmp(args[1], "expect") == 0) {
5081 const char *ptr_arg;
5082 int cur_arg;
5083
5084 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5085 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5086 err_code |= ERR_ALERT | ERR_FATAL;
5087 goto out;
5088 }
5089
5090 cur_arg = 2;
5091 /* consider exclamation marks, sole or at the beginning of a word */
5092 while (*(ptr_arg = args[cur_arg])) {
5093 while (*ptr_arg == '!') {
5094 curproxy->options2 ^= PR_O2_EXP_INV;
5095 ptr_arg++;
5096 }
5097 if (*ptr_arg)
5098 break;
5099 cur_arg++;
5100 }
5101 /* now ptr_arg points to the beginning of a word past any possible
5102 * exclamation mark, and cur_arg is the argument which holds this word.
5103 */
5104 if (strcmp(ptr_arg, "status") == 0) {
5105 if (!*(args[cur_arg + 1])) {
5106 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5107 file, linenum, args[0], args[1], ptr_arg);
5108 err_code |= ERR_ALERT | ERR_FATAL;
5109 goto out;
5110 }
5111 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005112 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005113 curproxy->expect_str = strdup(args[cur_arg + 1]);
5114 }
5115 else if (strcmp(ptr_arg, "string") == 0) {
5116 if (!*(args[cur_arg + 1])) {
5117 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5118 file, linenum, args[0], args[1], ptr_arg);
5119 err_code |= ERR_ALERT | ERR_FATAL;
5120 goto out;
5121 }
5122 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005123 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005124 curproxy->expect_str = strdup(args[cur_arg + 1]);
5125 }
5126 else if (strcmp(ptr_arg, "rstatus") == 0) {
5127 if (!*(args[cur_arg + 1])) {
5128 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5129 file, linenum, args[0], args[1], ptr_arg);
5130 err_code |= ERR_ALERT | ERR_FATAL;
5131 goto out;
5132 }
5133 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005134 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005135 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005136 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005137 free(curproxy->expect_regex);
5138 curproxy->expect_regex = NULL;
5139 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005140 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005141 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5142 error = NULL;
5143 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5144 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5145 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5146 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005147 err_code |= ERR_ALERT | ERR_FATAL;
5148 goto out;
5149 }
5150 }
5151 else if (strcmp(ptr_arg, "rstring") == 0) {
5152 if (!*(args[cur_arg + 1])) {
5153 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5154 file, linenum, args[0], args[1], ptr_arg);
5155 err_code |= ERR_ALERT | ERR_FATAL;
5156 goto out;
5157 }
5158 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005159 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005160 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005161 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005162 free(curproxy->expect_regex);
5163 curproxy->expect_regex = NULL;
5164 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005165 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005166 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5167 error = NULL;
5168 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5169 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5170 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5171 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005172 err_code |= ERR_ALERT | ERR_FATAL;
5173 goto out;
5174 }
5175 }
5176 else {
5177 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
5178 file, linenum, args[0], args[1], ptr_arg);
5179 err_code |= ERR_ALERT | ERR_FATAL;
5180 goto out;
5181 }
5182 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005183 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005184 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 +02005185 err_code |= ERR_ALERT | ERR_FATAL;
5186 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005187 }
5188 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005189 else if (!strcmp(args[0], "tcp-check")) {
5190 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5191 err_code |= ERR_WARN;
5192
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005193 if (strcmp(args[1], "comment") == 0) {
5194 int cur_arg;
5195 struct tcpcheck_rule *tcpcheck;
5196
5197 cur_arg = 1;
5198 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5199 tcpcheck->action = TCPCHK_ACT_COMMENT;
5200
5201 if (!*args[cur_arg + 1]) {
5202 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5203 file, linenum, args[cur_arg]);
5204 err_code |= ERR_ALERT | ERR_FATAL;
5205 goto out;
5206 }
5207
5208 tcpcheck->comment = strdup(args[cur_arg + 1]);
5209
5210 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
William Lallemanddf1425a2015-04-28 20:17:49 +02005211 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
5212 goto out;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005213 }
5214 else if (strcmp(args[1], "connect") == 0) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005215 const char *ptr_arg;
5216 int cur_arg;
5217 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005218
5219 /* check if first rule is also a 'connect' action */
Willy Tarreau5581c272015-05-13 12:24:53 +02005220 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
5221 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
5222 tcpcheck->action == TCPCHK_ACT_COMMENT) {
5223 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
5224 }
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005225
Willy Tarreau5581c272015-05-13 12:24:53 +02005226 if (&tcpcheck->list != &curproxy->tcpcheck_rules
5227 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
5228 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
5229 file, linenum);
5230 err_code |= ERR_ALERT | ERR_FATAL;
5231 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005232 }
5233
5234 cur_arg = 2;
5235 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5236 tcpcheck->action = TCPCHK_ACT_CONNECT;
5237
5238 /* parsing each parameters to fill up the rule */
5239 while (*(ptr_arg = args[cur_arg])) {
5240 /* tcp port */
5241 if (strcmp(args[cur_arg], "port") == 0) {
5242 if ( (atol(args[cur_arg + 1]) > 65535) ||
5243 (atol(args[cur_arg + 1]) < 1) ){
5244 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
5245 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
5246 err_code |= ERR_ALERT | ERR_FATAL;
5247 goto out;
5248 }
5249 tcpcheck->port = atol(args[cur_arg + 1]);
5250 cur_arg += 2;
5251 }
5252 /* send proxy protocol */
5253 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
5254 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
5255 cur_arg++;
5256 }
5257#ifdef USE_OPENSSL
5258 else if (strcmp(args[cur_arg], "ssl") == 0) {
5259 curproxy->options |= PR_O_TCPCHK_SSL;
5260 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
5261 cur_arg++;
5262 }
5263#endif /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005264 /* comment for this tcpcheck line */
5265 else if (strcmp(args[cur_arg], "comment") == 0) {
5266 if (!*args[cur_arg + 1]) {
5267 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5268 file, linenum, args[cur_arg]);
5269 err_code |= ERR_ALERT | ERR_FATAL;
5270 goto out;
5271 }
5272 tcpcheck->comment = strdup(args[cur_arg + 1]);
5273 cur_arg += 2;
5274 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005275 else {
5276#ifdef USE_OPENSSL
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005277 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 +01005278#else /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005279 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 +01005280#endif /* USE_OPENSSL */
5281 file, linenum, args[0], args[1], args[cur_arg]);
5282 err_code |= ERR_ALERT | ERR_FATAL;
5283 goto out;
5284 }
5285
5286 }
5287
5288 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5289 }
5290 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005291 if (! *(args[2]) ) {
5292 /* SEND string expected */
5293 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
5294 file, linenum, args[0], args[1], args[2]);
5295 err_code |= ERR_ALERT | ERR_FATAL;
5296 goto out;
5297 } else {
5298 struct tcpcheck_rule *tcpcheck;
5299
5300 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5301
5302 tcpcheck->action = TCPCHK_ACT_SEND;
5303 tcpcheck->string_len = strlen(args[2]);
5304 tcpcheck->string = strdup(args[2]);
5305 tcpcheck->expect_regex = NULL;
5306
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005307 /* comment for this tcpcheck line */
5308 if (strcmp(args[3], "comment") == 0) {
5309 if (!*args[4]) {
5310 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5311 file, linenum, args[3]);
5312 err_code |= ERR_ALERT | ERR_FATAL;
5313 goto out;
5314 }
5315 tcpcheck->comment = strdup(args[4]);
5316 }
5317
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005318 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5319 }
5320 }
5321 else if (strcmp(args[1], "send-binary") == 0) {
5322 if (! *(args[2]) ) {
5323 /* SEND binary string expected */
5324 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
5325 file, linenum, args[0], args[1], args[2]);
5326 err_code |= ERR_ALERT | ERR_FATAL;
5327 goto out;
5328 } else {
5329 struct tcpcheck_rule *tcpcheck;
5330 char *err = NULL;
5331
5332 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5333
5334 tcpcheck->action = TCPCHK_ACT_SEND;
5335 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5336 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5337 file, linenum, args[0], args[1], args[2], err);
5338 err_code |= ERR_ALERT | ERR_FATAL;
5339 goto out;
5340 }
5341 tcpcheck->expect_regex = NULL;
5342
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005343 /* comment for this tcpcheck line */
5344 if (strcmp(args[3], "comment") == 0) {
5345 if (!*args[4]) {
5346 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5347 file, linenum, args[3]);
5348 err_code |= ERR_ALERT | ERR_FATAL;
5349 goto out;
5350 }
5351 tcpcheck->comment = strdup(args[4]);
5352 }
5353
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005354 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5355 }
5356 }
5357 else if (strcmp(args[1], "expect") == 0) {
5358 const char *ptr_arg;
5359 int cur_arg;
5360 int inverse = 0;
5361
5362 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5363 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5364 err_code |= ERR_ALERT | ERR_FATAL;
5365 goto out;
5366 }
5367
5368 cur_arg = 2;
5369 /* consider exclamation marks, sole or at the beginning of a word */
5370 while (*(ptr_arg = args[cur_arg])) {
5371 while (*ptr_arg == '!') {
5372 inverse = !inverse;
5373 ptr_arg++;
5374 }
5375 if (*ptr_arg)
5376 break;
5377 cur_arg++;
5378 }
5379 /* now ptr_arg points to the beginning of a word past any possible
5380 * exclamation mark, and cur_arg is the argument which holds this word.
5381 */
5382 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005383 struct tcpcheck_rule *tcpcheck;
5384 char *err = NULL;
5385
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005386 if (!*(args[cur_arg + 1])) {
5387 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
5388 file, linenum, args[0], args[1], ptr_arg);
5389 err_code |= ERR_ALERT | ERR_FATAL;
5390 goto out;
5391 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005392
5393 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5394
5395 tcpcheck->action = TCPCHK_ACT_EXPECT;
5396 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5397 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5398 file, linenum, args[0], args[1], args[2], err);
5399 err_code |= ERR_ALERT | ERR_FATAL;
5400 goto out;
5401 }
5402 tcpcheck->expect_regex = NULL;
5403 tcpcheck->inverse = inverse;
5404
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005405 /* tcpcheck comment */
5406 cur_arg += 2;
5407 if (strcmp(args[cur_arg], "comment") == 0) {
5408 if (!*args[cur_arg + 1]) {
5409 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5410 file, linenum, args[cur_arg + 1]);
5411 err_code |= ERR_ALERT | ERR_FATAL;
5412 goto out;
5413 }
5414 tcpcheck->comment = strdup(args[cur_arg + 1]);
5415 }
5416
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005417 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5418 }
5419 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005420 struct tcpcheck_rule *tcpcheck;
5421
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005422 if (!*(args[cur_arg + 1])) {
5423 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5424 file, linenum, args[0], args[1], ptr_arg);
5425 err_code |= ERR_ALERT | ERR_FATAL;
5426 goto out;
5427 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005428
5429 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5430
5431 tcpcheck->action = TCPCHK_ACT_EXPECT;
5432 tcpcheck->string_len = strlen(args[cur_arg + 1]);
5433 tcpcheck->string = strdup(args[cur_arg + 1]);
5434 tcpcheck->expect_regex = NULL;
5435 tcpcheck->inverse = inverse;
5436
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005437 /* tcpcheck comment */
5438 cur_arg += 2;
5439 if (strcmp(args[cur_arg], "comment") == 0) {
5440 if (!*args[cur_arg + 1]) {
5441 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5442 file, linenum, args[cur_arg + 1]);
5443 err_code |= ERR_ALERT | ERR_FATAL;
5444 goto out;
5445 }
5446 tcpcheck->comment = strdup(args[cur_arg + 1]);
5447 }
5448
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005449 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5450 }
5451 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005452 struct tcpcheck_rule *tcpcheck;
5453
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005454 if (!*(args[cur_arg + 1])) {
5455 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5456 file, linenum, args[0], args[1], ptr_arg);
5457 err_code |= ERR_ALERT | ERR_FATAL;
5458 goto out;
5459 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005460
5461 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5462
5463 tcpcheck->action = TCPCHK_ACT_EXPECT;
5464 tcpcheck->string_len = 0;
5465 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005466 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
5467 error = NULL;
5468 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
5469 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5470 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5471 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005472 err_code |= ERR_ALERT | ERR_FATAL;
5473 goto out;
5474 }
5475 tcpcheck->inverse = inverse;
5476
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005477 /* tcpcheck comment */
5478 cur_arg += 2;
5479 if (strcmp(args[cur_arg], "comment") == 0) {
5480 if (!*args[cur_arg + 1]) {
5481 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5482 file, linenum, args[cur_arg + 1]);
5483 err_code |= ERR_ALERT | ERR_FATAL;
5484 goto out;
5485 }
5486 tcpcheck->comment = strdup(args[cur_arg + 1]);
5487 }
5488
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005489 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5490 }
5491 else {
5492 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
5493 file, linenum, args[0], args[1], ptr_arg);
5494 err_code |= ERR_ALERT | ERR_FATAL;
5495 goto out;
5496 }
5497 }
5498 else {
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005499 Alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005500 err_code |= ERR_ALERT | ERR_FATAL;
5501 goto out;
5502 }
5503 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01005504 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02005505 if (curproxy == &defproxy) {
5506 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005507 err_code |= ERR_ALERT | ERR_FATAL;
5508 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02005509 }
5510
Willy Tarreaub80c2302007-11-30 20:51:32 +01005511 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005512 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005513
5514 if (strcmp(args[1], "fail") == 0) {
5515 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01005516 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01005517 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
5518 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005519 err_code |= ERR_ALERT | ERR_FATAL;
5520 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005521 }
5522
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005523 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
5524 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
5525 file, linenum, args[0], args[1], errmsg);
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 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
5530 }
5531 else {
5532 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
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 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005537#ifdef TPROXY
5538 else if (!strcmp(args[0], "transparent")) {
5539 /* enable transparent proxy connections */
5540 curproxy->options |= PR_O_TRANSP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005541 if (alertif_too_many_args(0, file, linenum, args, &err_code))
5542 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005543 }
5544#endif
5545 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005546 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005547 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005548
Willy Tarreaubaaee002006-06-26 02:48:02 +02005549 if (*(args[1]) == 0) {
5550 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005551 err_code |= ERR_ALERT | ERR_FATAL;
5552 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005553 }
5554 curproxy->maxconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005555 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5556 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005557 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005558 else if (!strcmp(args[0], "backlog")) { /* backlog */
5559 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005560 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005561
5562 if (*(args[1]) == 0) {
5563 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005564 err_code |= ERR_ALERT | ERR_FATAL;
5565 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005566 }
5567 curproxy->backlog = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005568 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5569 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005570 }
Willy Tarreau86034312006-12-29 00:10:33 +01005571 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005572 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005573 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005574
Willy Tarreau86034312006-12-29 00:10:33 +01005575 if (*(args[1]) == 0) {
5576 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005577 err_code |= ERR_ALERT | ERR_FATAL;
5578 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005579 }
5580 curproxy->fullconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005581 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5582 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005583 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005584 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
5585 if (*(args[1]) == 0) {
5586 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005587 err_code |= ERR_ALERT | ERR_FATAL;
5588 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005589 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005590 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
5591 if (err) {
5592 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
5593 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02005594 err_code |= ERR_ALERT | ERR_FATAL;
5595 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005596 }
5597 curproxy->grace = val;
William Lallemanddf1425a2015-04-28 20:17:49 +02005598 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5599 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005600 }
5601 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01005602 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005603 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005604 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005605
Willy Tarreaubaaee002006-06-26 02:48:02 +02005606 if (curproxy == &defproxy) {
5607 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005608 err_code |= ERR_ALERT | ERR_FATAL;
5609 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005610 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005611 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005612 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005613
Willy Tarreau72b8c1f2015-09-08 15:50:19 +02005614 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005615 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005616 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005617 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005618 goto out;
5619 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005620
5621 proto = protocol_by_family(sk->ss_family);
5622 if (!proto || !proto->connect) {
5623 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5624 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005625 err_code |= ERR_ALERT | ERR_FATAL;
5626 goto out;
5627 }
5628
5629 if (port1 != port2) {
5630 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5631 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005632 err_code |= ERR_ALERT | ERR_FATAL;
5633 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005634 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005635
5636 if (!port1) {
5637 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5638 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005639 err_code |= ERR_ALERT | ERR_FATAL;
5640 goto out;
5641 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005642
William Lallemanddf1425a2015-04-28 20:17:49 +02005643 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5644 goto out;
5645
Willy Tarreaud5191e72010-02-09 20:50:45 +01005646 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005647 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005648 }
5649 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005650 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005651 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005652
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005653 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5654 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005655 err_code |= ERR_ALERT | ERR_FATAL;
5656 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005657 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005658 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005659 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005660 /**
5661 * The syntax for hash-type config element is
5662 * hash-type {map-based|consistent} [[<algo>] avalanche]
5663 *
5664 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5665 */
5666 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005667
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005668 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5669 err_code |= ERR_WARN;
5670
5671 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005672 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5673 }
5674 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005675 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5676 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005677 else if (strcmp(args[1], "avalanche") == 0) {
5678 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]);
5679 err_code |= ERR_ALERT | ERR_FATAL;
5680 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005681 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005682 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005683 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005684 err_code |= ERR_ALERT | ERR_FATAL;
5685 goto out;
5686 }
Bhaskar98634f02013-10-29 23:30:51 -04005687
5688 /* set the hash function to use */
5689 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005690 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005691 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005692
5693 /* if consistent with no argument, then avalanche modifier is also applied */
5694 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5695 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005696 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005697 /* set the hash function */
5698 if (!strcmp(args[2], "sdbm")) {
5699 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5700 }
5701 else if (!strcmp(args[2], "djb2")) {
5702 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005703 }
5704 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005705 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005706 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005707 else if (!strcmp(args[2], "crc32")) {
5708 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5709 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005710 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005711 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 -05005712 err_code |= ERR_ALERT | ERR_FATAL;
5713 goto out;
5714 }
5715
5716 /* set the hash modifier */
5717 if (!strcmp(args[3], "avalanche")) {
5718 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5719 }
5720 else if (*args[3]) {
5721 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5722 err_code |= ERR_ALERT | ERR_FATAL;
5723 goto out;
5724 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005725 }
William Lallemanda73203e2012-03-12 12:48:57 +01005726 }
William Lallemanda73203e2012-03-12 12:48:57 +01005727 else if (strcmp(args[0], "unique-id-format") == 0) {
5728 if (!*(args[1])) {
5729 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5730 err_code |= ERR_ALERT | ERR_FATAL;
5731 goto out;
5732 }
William Lallemand3203ff42012-11-11 17:30:56 +01005733 if (*(args[2])) {
5734 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5735 err_code |= ERR_ALERT | ERR_FATAL;
5736 goto out;
5737 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005738 free(curproxy->conf.uniqueid_format_string);
5739 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005740
Willy Tarreau62a61232013-04-12 18:13:46 +02005741 free(curproxy->conf.uif_file);
5742 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5743 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005744 }
William Lallemanda73203e2012-03-12 12:48:57 +01005745
5746 else if (strcmp(args[0], "unique-id-header") == 0) {
5747 if (!*(args[1])) {
5748 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5749 err_code |= ERR_ALERT | ERR_FATAL;
5750 goto out;
5751 }
5752 free(curproxy->header_unique_id);
5753 curproxy->header_unique_id = strdup(args[1]);
5754 }
5755
William Lallemand723b73a2012-02-08 16:37:49 +01005756 else if (strcmp(args[0], "log-format") == 0) {
5757 if (!*(args[1])) {
5758 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5759 err_code |= ERR_ALERT | ERR_FATAL;
5760 goto out;
5761 }
William Lallemand3203ff42012-11-11 17:30:56 +01005762 if (*(args[2])) {
5763 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5764 err_code |= ERR_ALERT | ERR_FATAL;
5765 goto out;
5766 }
Willy Tarreau196729e2012-05-31 19:30:26 +02005767
Willy Tarreau62a61232013-04-12 18:13:46 +02005768 if (curproxy->conf.logformat_string != default_http_log_format &&
5769 curproxy->conf.logformat_string != default_tcp_log_format &&
5770 curproxy->conf.logformat_string != clf_http_log_format)
5771 free(curproxy->conf.logformat_string);
5772 curproxy->conf.logformat_string = strdup(args[1]);
5773
5774 free(curproxy->conf.lfs_file);
5775 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5776 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005777
5778 /* get a chance to improve log-format error reporting by
5779 * reporting the correct line-number when possible.
5780 */
5781 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5782 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5783 file, linenum, curproxy->id);
5784 err_code |= ERR_WARN;
5785 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005786 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01005787 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
5788 if (*(args[1]) == 0) {
5789 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
5790 err_code |= ERR_ALERT | ERR_FATAL;
5791 goto out;
5792 }
5793 free(curproxy->log_tag);
5794 curproxy->log_tag = strdup(args[1]);
5795 }
William Lallemand0f99e342011-10-12 17:50:54 +02005796 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
5797 /* delete previous herited or defined syslog servers */
5798 struct logsrv *back;
5799
5800 if (*(args[1]) != 0) {
5801 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
5802 err_code |= ERR_ALERT | ERR_FATAL;
5803 goto out;
5804 }
5805
William Lallemand723b73a2012-02-08 16:37:49 +01005806 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
5807 LIST_DEL(&tmplogsrv->list);
5808 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02005809 }
5810 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005811 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02005812 struct logsrv *logsrv;
5813
Willy Tarreaubaaee002006-06-26 02:48:02 +02005814 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005815 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01005816 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02005817 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01005818 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02005819 LIST_INIT(&node->list);
5820 LIST_ADDQ(&curproxy->logsrvs, &node->list);
5821 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005822 }
5823 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005824 struct sockaddr_storage *sk;
5825 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02005826 int arg = 0;
5827 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02005828
5829 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005830
Willy Tarreau18324f52014-06-27 18:10:07 +02005831 /* just after the address, a length may be specified */
5832 if (strcmp(args[arg+2], "len") == 0) {
5833 len = atoi(args[arg+3]);
5834 if (len < 80 || len > 65535) {
5835 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
5836 file, linenum, args[arg+3]);
5837 err_code |= ERR_ALERT | ERR_FATAL;
5838 goto out;
5839 }
5840 logsrv->maxlen = len;
5841
5842 /* skip these two args */
5843 arg += 2;
5844 }
5845 else
5846 logsrv->maxlen = MAX_SYSLOG_LEN;
5847
5848 if (logsrv->maxlen > global.max_syslog_len) {
5849 global.max_syslog_len = logsrv->maxlen;
5850 logline = realloc(logline, global.max_syslog_len + 1);
5851 }
5852
William Lallemanddf1425a2015-04-28 20:17:49 +02005853 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
5854 goto out;
5855
Willy Tarreau18324f52014-06-27 18:10:07 +02005856 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005857 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005858 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005859 err_code |= ERR_ALERT | ERR_FATAL;
5860 goto out;
5861
Willy Tarreaubaaee002006-06-26 02:48:02 +02005862 }
5863
William Lallemand0f99e342011-10-12 17:50:54 +02005864 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02005865 if (*(args[arg+3])) {
5866 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005867 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005868 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005869 err_code |= ERR_ALERT | ERR_FATAL;
5870 goto out;
5871
Willy Tarreaubaaee002006-06-26 02:48:02 +02005872 }
5873 }
5874
William Lallemand0f99e342011-10-12 17:50:54 +02005875 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02005876 if (*(args[arg+4])) {
5877 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01005878 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005879 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02005880 err_code |= ERR_ALERT | ERR_FATAL;
5881 goto out;
5882
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005883 }
5884 }
5885
Willy Tarreau72b8c1f2015-09-08 15:50:19 +02005886 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005887 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005888 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005889 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005890 goto out;
5891 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005892
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005893 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005894
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005895 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005896 if (port1 != port2) {
5897 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5898 file, linenum, args[0], args[1]);
5899 err_code |= ERR_ALERT | ERR_FATAL;
5900 goto out;
5901 }
5902
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005903 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02005904 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005905 }
William Lallemand0f99e342011-10-12 17:50:54 +02005906
5907 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005908 }
5909 else {
5910 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
5911 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005912 err_code |= ERR_ALERT | ERR_FATAL;
5913 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005914 }
5915 }
5916 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005917 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005918 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01005919 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005920 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005921
Willy Tarreau977b8e42006-12-29 14:19:17 +01005922 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005923 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005924
Willy Tarreaubaaee002006-06-26 02:48:02 +02005925 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005926 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
5927 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005928 err_code |= ERR_ALERT | ERR_FATAL;
5929 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005930 }
Willy Tarreau368480c2009-03-01 08:27:21 +01005931
5932 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01005933 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5934 free(curproxy->conn_src.iface_name);
5935 curproxy->conn_src.iface_name = NULL;
5936 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01005937
Willy Tarreau72b8c1f2015-09-08 15:50:19 +02005938 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005939 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005940 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005941 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005942 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005943 goto out;
5944 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005945
5946 proto = protocol_by_family(sk->ss_family);
5947 if (!proto || !proto->connect) {
5948 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005949 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005950 err_code |= ERR_ALERT | ERR_FATAL;
5951 goto out;
5952 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005953
5954 if (port1 != port2) {
5955 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5956 file, linenum, args[0], args[1]);
5957 err_code |= ERR_ALERT | ERR_FATAL;
5958 goto out;
5959 }
5960
Willy Tarreauef9a3602012-12-08 22:29:20 +01005961 curproxy->conn_src.source_addr = *sk;
5962 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005963
5964 cur_arg = 2;
5965 while (*(args[cur_arg])) {
5966 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau29fbe512015-08-20 19:35:14 +02005967#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005968 if (!*args[cur_arg + 1]) {
5969 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5970 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005971 err_code |= ERR_ALERT | ERR_FATAL;
5972 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005973 }
5974
5975 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005976 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5977 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005978 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005979 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5980 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005981 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5982 char *name, *end;
5983
5984 name = args[cur_arg+1] + 7;
5985 while (isspace(*name))
5986 name++;
5987
5988 end = name;
5989 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5990 end++;
5991
Willy Tarreauef9a3602012-12-08 22:29:20 +01005992 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5993 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5994 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5995 curproxy->conn_src.bind_hdr_len = end - name;
5996 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5997 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5998 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005999
6000 /* now look for an occurrence number */
6001 while (isspace(*end))
6002 end++;
6003 if (*end == ',') {
6004 end++;
6005 name = end;
6006 if (*end == '-')
6007 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01006008 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02006009 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01006010 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006011 }
6012
Willy Tarreauef9a3602012-12-08 22:29:20 +01006013 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02006014 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
6015 " occurrences values smaller than %d.\n",
6016 file, linenum, MAX_HDR_HISTORY);
6017 err_code |= ERR_ALERT | ERR_FATAL;
6018 goto out;
6019 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006020 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01006021 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006022
Willy Tarreau72b8c1f2015-09-08 15:50:19 +02006023 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006024 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006025 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006026 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006027 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006028 goto out;
6029 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006030
6031 proto = protocol_by_family(sk->ss_family);
6032 if (!proto || !proto->connect) {
6033 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
6034 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006035 err_code |= ERR_ALERT | ERR_FATAL;
6036 goto out;
6037 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006038
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006039 if (port1 != port2) {
6040 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6041 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006042 err_code |= ERR_ALERT | ERR_FATAL;
6043 goto out;
6044 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006045 curproxy->conn_src.tproxy_addr = *sk;
6046 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006047 }
6048 global.last_checks |= LSTCHK_NETADM;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006049#else /* no TPROXY support */
6050 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01006051 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006052 err_code |= ERR_ALERT | ERR_FATAL;
6053 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006054#endif
6055 cur_arg += 2;
6056 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01006057 }
6058
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006059 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
6060#ifdef SO_BINDTODEVICE
6061 if (!*args[cur_arg + 1]) {
6062 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
6063 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006064 err_code |= ERR_ALERT | ERR_FATAL;
6065 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006066 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006067 free(curproxy->conn_src.iface_name);
6068 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
6069 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006070 global.last_checks |= LSTCHK_NETADM;
6071#else
6072 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
6073 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02006074 err_code |= ERR_ALERT | ERR_FATAL;
6075 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01006076#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006077 cur_arg += 2;
6078 continue;
6079 }
6080 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02006081 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006082 err_code |= ERR_ALERT | ERR_FATAL;
6083 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006084 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006085 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006086 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
6087 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
6088 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02006089 err_code |= ERR_ALERT | ERR_FATAL;
6090 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006091 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006092 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006093 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006094 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6095 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006096 err_code |= ERR_ALERT | ERR_FATAL;
6097 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006098 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006099
6100 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006101 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006102 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006103 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006104 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006105 }
6106 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006107 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006108 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006109 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006110 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006111 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006112 }
6113 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006114 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006115 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006116 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006117 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006118 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006119 }
6120 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006121 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006122 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006123 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006124 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006125 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006126 }
6127 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006128 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006129 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006130 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006131 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006132 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006133 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006134 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006135 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006136 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006137 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006138 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006139 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006140 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006141 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006142 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006143 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6144 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006145 err_code |= ERR_ALERT | ERR_FATAL;
6146 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006147 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006148
6149 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006150 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006151 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006152 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006153 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006154 }
6155 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006156 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006157 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006158 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006159 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006160 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006161 }
6162 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006163 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006164 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006165 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006166 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006167 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006168 }
6169 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006170 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006171 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006172 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006173 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006174 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006175 }
6176 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006177 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006178 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006179 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006180 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006181 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006182 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006183 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006184 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006185 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006186 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006187 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006188 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006189 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006190 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006191 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006192
Willy Tarreaubaaee002006-06-26 02:48:02 +02006193 if (curproxy == &defproxy) {
6194 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006195 err_code |= ERR_ALERT | ERR_FATAL;
6196 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006197 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006198 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006199 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006200
Willy Tarreaubaaee002006-06-26 02:48:02 +02006201 if (*(args[1]) == 0) {
6202 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\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 Tarreaudeb9ed82010-01-03 21:03:22 +01006206
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006207 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006208 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6209 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6210 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006211 err_code |= ERR_ALERT | ERR_FATAL;
6212 goto out;
6213 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006214 err_code |= warnif_cond_conflicts(cond,
6215 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6216 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006217 }
6218 else if (*args[2]) {
6219 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6220 file, linenum, args[0], args[2]);
6221 err_code |= ERR_ALERT | ERR_FATAL;
6222 goto out;
6223 }
6224
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006225 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006226 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006227 wl->s = strdup(args[1]);
6228 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02006229 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006230 }
6231 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006232 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006233 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6234 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006235 err_code |= ERR_ALERT | ERR_FATAL;
6236 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006237 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006238
Willy Tarreauade5ec42010-01-28 19:33:49 +01006239 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006240 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006241 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006242 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006243 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006244 }
6245 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006246 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006247 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006248 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006249 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006250 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006251 }
6252 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006253 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006254 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006255 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006256 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006257 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006258 }
6259 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006260 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006261 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6262 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006263 err_code |= ERR_ALERT | ERR_FATAL;
6264 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006265 }
6266
Willy Tarreauade5ec42010-01-28 19:33:49 +01006267 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006268 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006269 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006270 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006271 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006272 }
6273 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006274 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006275 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006276 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006277 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006278 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006279 }
6280 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006281 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006282 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006283 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006284 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006285 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006286 }
6287 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006288 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006289
Willy Tarreaubaaee002006-06-26 02:48:02 +02006290 if (curproxy == &defproxy) {
6291 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006292 err_code |= ERR_ALERT | ERR_FATAL;
6293 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006294 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006295 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006296 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006297
Willy Tarreaubaaee002006-06-26 02:48:02 +02006298 if (*(args[1]) == 0) {
6299 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\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 }
6303
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006304 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006305 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6306 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6307 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006308 err_code |= ERR_ALERT | ERR_FATAL;
6309 goto out;
6310 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006311 err_code |= warnif_cond_conflicts(cond,
6312 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
6313 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006314 }
6315 else if (*args[2]) {
6316 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6317 file, linenum, args[0], args[2]);
6318 err_code |= ERR_ALERT | ERR_FATAL;
6319 goto out;
6320 }
6321
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006322 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006323 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006324 wl->s = strdup(args[1]);
6325 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006326 }
6327 else if (!strcmp(args[0], "errorloc") ||
6328 !strcmp(args[0], "errorloc302") ||
6329 !strcmp(args[0], "errorloc303")) { /* error location */
6330 int errnum, errlen;
6331 char *err;
6332
Willy Tarreau977b8e42006-12-29 14:19:17 +01006333 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006334 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006335
Willy Tarreaubaaee002006-06-26 02:48:02 +02006336 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006337 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006338 err_code |= ERR_ALERT | ERR_FATAL;
6339 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006340 }
6341
6342 errnum = atol(args[1]);
6343 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006344 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
6345 err = malloc(errlen);
6346 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006347 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006348 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
6349 err = malloc(errlen);
6350 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006351 }
6352
Willy Tarreau0f772532006-12-23 20:51:41 +01006353 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6354 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006355 chunk_destroy(&curproxy->errmsg[rc]);
6356 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01006357 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006358 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006359 }
Willy Tarreau0f772532006-12-23 20:51:41 +01006360
6361 if (rc >= HTTP_ERR_SIZE) {
6362 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
6363 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006364 free(err);
6365 }
6366 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02006367 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
6368 int errnum, errlen, fd;
6369 char *err;
6370 struct stat stat;
6371
6372 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006373 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006374
6375 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006376 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006377 err_code |= ERR_ALERT | ERR_FATAL;
6378 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006379 }
6380
6381 fd = open(args[2], O_RDONLY);
6382 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
6383 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
6384 file, linenum, args[2], args[1]);
6385 if (fd >= 0)
6386 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02006387 err_code |= ERR_ALERT | ERR_FATAL;
6388 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006389 }
6390
Willy Tarreau27a674e2009-08-17 07:23:33 +02006391 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02006392 errlen = stat.st_size;
6393 } else {
6394 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02006395 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02006396 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02006397 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006398 }
6399
6400 err = malloc(errlen); /* malloc() must succeed during parsing */
6401 errnum = read(fd, err, errlen);
6402 if (errnum != errlen) {
6403 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
6404 file, linenum, args[2], args[1]);
6405 close(fd);
6406 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02006407 err_code |= ERR_ALERT | ERR_FATAL;
6408 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006409 }
6410 close(fd);
6411
6412 errnum = atol(args[1]);
6413 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6414 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006415 chunk_destroy(&curproxy->errmsg[rc]);
6416 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02006417 break;
6418 }
6419 }
6420
6421 if (rc >= HTTP_ERR_SIZE) {
6422 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
6423 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02006424 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006425 free(err);
6426 }
6427 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006428 else if (!strcmp(args[0], "compression")) {
6429 struct comp *comp;
6430 if (curproxy->comp == NULL) {
6431 comp = calloc(1, sizeof(struct comp));
6432 curproxy->comp = comp;
6433 } else {
6434 comp = curproxy->comp;
6435 }
6436
6437 if (!strcmp(args[1], "algo")) {
6438 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01006439 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01006440
William Lallemand82fe75c2012-10-23 10:25:10 +02006441 cur_arg = 2;
6442 if (!*args[cur_arg]) {
6443 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
6444 file, linenum, args[0]);
6445 err_code |= ERR_ALERT | ERR_FATAL;
6446 goto out;
6447 }
6448 while (*(args[cur_arg])) {
6449 if (comp_append_algo(comp, args[cur_arg]) < 0) {
6450 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
6451 file, linenum, args[0], args[cur_arg]);
6452 err_code |= ERR_ALERT | ERR_FATAL;
6453 goto out;
6454 }
William Lallemand552df672012-11-07 13:21:47 +01006455 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
6456 curproxy->comp->algos->end(&ctx);
6457 } else {
6458 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
6459 file, linenum, args[0], args[cur_arg]);
6460 err_code |= ERR_ALERT | ERR_FATAL;
6461 goto out;
6462 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006463 cur_arg ++;
6464 continue;
6465 }
6466 }
Willy Tarreau70737d12012-10-27 00:34:28 +02006467 else if (!strcmp(args[1], "offload")) {
6468 comp->offload = 1;
6469 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006470 else if (!strcmp(args[1], "type")) {
6471 int cur_arg;
6472 cur_arg = 2;
6473 if (!*args[cur_arg]) {
6474 Alert("parsing [%s:%d] : '%s' expects <type>\n",
6475 file, linenum, args[0]);
6476 err_code |= ERR_ALERT | ERR_FATAL;
6477 goto out;
6478 }
6479 while (*(args[cur_arg])) {
6480 comp_append_type(comp, args[cur_arg]);
6481 cur_arg ++;
6482 continue;
6483 }
6484 }
6485 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02006486 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02006487 file, linenum, args[0]);
6488 err_code |= ERR_ALERT | ERR_FATAL;
6489 goto out;
6490 }
6491 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006492 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006493 struct cfg_kw_list *kwl;
6494 int index;
6495
6496 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6497 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6498 if (kwl->kw[index].section != CFG_LISTEN)
6499 continue;
6500 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6501 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006502 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006503 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006504 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006505 err_code |= ERR_ALERT | ERR_FATAL;
6506 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006507 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006508 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006509 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006510 err_code |= ERR_WARN;
6511 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006512 }
Willy Tarreau93893792009-07-23 13:19:11 +02006513 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006514 }
6515 }
6516 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006517
Willy Tarreau6daf3432008-01-22 16:44:08 +01006518 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006519 err_code |= ERR_ALERT | ERR_FATAL;
6520 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006521 }
Willy Tarreau93893792009-07-23 13:19:11 +02006522 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006523 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006524 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006525}
6526
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006527int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006528cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
6529{
6530#ifdef CONFIG_HAP_NS
6531 const char *err;
6532 const char *item = args[0];
6533
6534 if (!strcmp(item, "namespace_list")) {
6535 return 0;
6536 }
6537 else if (!strcmp(item, "namespace")) {
6538 size_t idx = 1;
6539 const char *current;
6540 while (*(current = args[idx++])) {
6541 err = invalid_char(current);
6542 if (err) {
6543 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6544 file, linenum, *err, item, current);
6545 return ERR_ALERT | ERR_FATAL;
6546 }
6547
6548 if (netns_store_lookup(current, strlen(current))) {
6549 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
6550 file, linenum, current);
6551 return ERR_ALERT | ERR_FATAL;
6552 }
6553 if (!netns_store_insert(current)) {
6554 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
6555 file, linenum, current);
6556 return ERR_ALERT | ERR_FATAL;
6557 }
6558 }
6559 }
6560
6561 return 0;
6562#else
6563 Alert("parsing [%s:%d]: namespace support is not compiled in.",
6564 file, linenum);
6565 return ERR_ALERT | ERR_FATAL;
6566#endif
6567}
6568
6569int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006570cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6571{
6572
6573 int err_code = 0;
6574 const char *err;
6575
6576 if (!strcmp(args[0], "userlist")) { /* new userlist */
6577 struct userlist *newul;
6578
6579 if (!*args[1]) {
6580 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6581 file, linenum, args[0]);
6582 err_code |= ERR_ALERT | ERR_FATAL;
6583 goto out;
6584 }
William Lallemand6e62fb62015-04-28 16:55:23 +02006585 if (alertif_too_many_args(1, file, linenum, args, &err_code))
6586 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006587
6588 err = invalid_char(args[1]);
6589 if (err) {
6590 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6591 file, linenum, *err, args[0], args[1]);
6592 err_code |= ERR_ALERT | ERR_FATAL;
6593 goto out;
6594 }
6595
6596 for (newul = userlist; newul; newul = newul->next)
6597 if (!strcmp(newul->name, args[1])) {
6598 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6599 file, linenum, args[1]);
6600 err_code |= ERR_WARN;
6601 goto out;
6602 }
6603
6604 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
6605 if (!newul) {
6606 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6607 err_code |= ERR_ALERT | ERR_ABORT;
6608 goto out;
6609 }
6610
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006611 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006612 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006613 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6614 err_code |= ERR_ALERT | ERR_ABORT;
6615 goto out;
6616 }
6617
6618 newul->next = userlist;
6619 userlist = newul;
6620
6621 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006622 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006623 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006624 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006625
6626 if (!*args[1]) {
6627 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6628 file, linenum, args[0]);
6629 err_code |= ERR_ALERT | ERR_FATAL;
6630 goto out;
6631 }
6632
6633 err = invalid_char(args[1]);
6634 if (err) {
6635 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6636 file, linenum, *err, args[0], args[1]);
6637 err_code |= ERR_ALERT | ERR_FATAL;
6638 goto out;
6639 }
6640
William Lallemand4ac9f542015-05-28 18:03:51 +02006641 if (!userlist)
6642 goto out;
6643
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006644 for (ag = userlist->groups; ag; ag = ag->next)
6645 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006646 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6647 file, linenum, args[1], userlist->name);
6648 err_code |= ERR_ALERT;
6649 goto out;
6650 }
6651
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006652 ag = calloc(1, sizeof(*ag));
6653 if (!ag) {
6654 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6655 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006656 goto out;
6657 }
6658
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006659 ag->name = strdup(args[1]);
6660 if (!ag) {
6661 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6662 err_code |= ERR_ALERT | ERR_ABORT;
6663 goto out;
6664 }
6665
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006666 cur_arg = 2;
6667
6668 while (*args[cur_arg]) {
6669 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006670 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006671 cur_arg += 2;
6672 continue;
6673 } else {
6674 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6675 file, linenum, args[0]);
6676 err_code |= ERR_ALERT | ERR_FATAL;
6677 goto out;
6678 }
6679 }
6680
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006681 ag->next = userlist->groups;
6682 userlist->groups = ag;
6683
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006684 } else if (!strcmp(args[0], "user")) { /* new user */
6685 struct auth_users *newuser;
6686 int cur_arg;
6687
6688 if (!*args[1]) {
6689 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6690 file, linenum, args[0]);
6691 err_code |= ERR_ALERT | ERR_FATAL;
6692 goto out;
6693 }
William Lallemand4ac9f542015-05-28 18:03:51 +02006694 if (!userlist)
6695 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006696
6697 for (newuser = userlist->users; newuser; newuser = newuser->next)
6698 if (!strcmp(newuser->user, args[1])) {
6699 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6700 file, linenum, args[1], userlist->name);
6701 err_code |= ERR_ALERT;
6702 goto out;
6703 }
6704
6705 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
6706 if (!newuser) {
6707 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6708 err_code |= ERR_ALERT | ERR_ABORT;
6709 goto out;
6710 }
6711
6712 newuser->user = strdup(args[1]);
6713
6714 newuser->next = userlist->users;
6715 userlist->users = newuser;
6716
6717 cur_arg = 2;
6718
6719 while (*args[cur_arg]) {
6720 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006721#ifdef CONFIG_HAP_CRYPT
6722 if (!crypt("", args[cur_arg + 1])) {
6723 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6724 file, linenum, newuser->user);
6725 err_code |= ERR_ALERT | ERR_FATAL;
6726 goto out;
6727 }
6728#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006729 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6730 file, linenum);
6731 err_code |= ERR_ALERT;
6732#endif
6733 newuser->pass = strdup(args[cur_arg + 1]);
6734 cur_arg += 2;
6735 continue;
6736 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6737 newuser->pass = strdup(args[cur_arg + 1]);
6738 newuser->flags |= AU_O_INSECURE;
6739 cur_arg += 2;
6740 continue;
6741 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006742 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006743 cur_arg += 2;
6744 continue;
6745 } else {
6746 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6747 file, linenum, args[0]);
6748 err_code |= ERR_ALERT | ERR_FATAL;
6749 goto out;
6750 }
6751 }
6752 } else {
6753 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6754 err_code |= ERR_ALERT | ERR_FATAL;
6755 }
6756
6757out:
6758 return err_code;
6759}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006760
6761/*
6762 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006763 * Returns the error code, 0 if OK, or any combination of :
6764 * - ERR_ABORT: must abort ASAP
6765 * - ERR_FATAL: we can continue parsing but not start the service
6766 * - ERR_WARN: a warning has been emitted
6767 * - ERR_ALERT: an alert has been emitted
6768 * Only the two first ones can stop processing, the two others are just
6769 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006770 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006771int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006772{
William Lallemand64e84512015-05-12 14:25:37 +02006773 char *thisline;
6774 int linesize = LINESIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006775 FILE *f;
6776 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02006777 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006778 struct cfg_section *cs = NULL;
6779 struct cfg_section *ics;
William Lallemand64e84512015-05-12 14:25:37 +02006780 int readbytes = 0;
6781
6782 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
William Lallemandb2f07452015-05-12 14:27:13 +02006783 Alert("parsing [%s] : out of memory.\n", file);
William Lallemand64e84512015-05-12 14:25:37 +02006784 return -1;
6785 }
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006786
6787 /* Register internal sections */
6788 if (!cfg_register_section("listen", cfg_parse_listen) ||
6789 !cfg_register_section("frontend", cfg_parse_listen) ||
6790 !cfg_register_section("backend", cfg_parse_listen) ||
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006791 !cfg_register_section("defaults", cfg_parse_listen) ||
6792 !cfg_register_section("global", cfg_parse_global) ||
6793 !cfg_register_section("userlist", cfg_parse_users) ||
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006794 !cfg_register_section("peers", cfg_parse_peers) ||
Simon Horman0d16a402015-01-30 11:22:58 +09006795 !cfg_register_section("mailers", cfg_parse_mailers) ||
Baptiste Assmann325137d2015-04-13 23:40:55 +02006796 !cfg_register_section("namespace_list", cfg_parse_netns) ||
6797 !cfg_register_section("resolvers", cfg_parse_resolvers))
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006798 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006799
Willy Tarreaubaaee002006-06-26 02:48:02 +02006800 if ((f=fopen(file,"r")) == NULL)
6801 return -1;
6802
William Lallemandb2f07452015-05-12 14:27:13 +02006803next_line:
William Lallemand64e84512015-05-12 14:25:37 +02006804 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02006805 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006806 char *end;
6807 char *args[MAX_LINE_ARGS + 1];
6808 char *line = thisline;
William Lallemandf9873ba2015-05-05 17:37:14 +02006809 int dquote = 0; /* double quote */
6810 int squote = 0; /* simple quote */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006811
Willy Tarreaubaaee002006-06-26 02:48:02 +02006812 linenum++;
6813
6814 end = line + strlen(line);
6815
William Lallemand64e84512015-05-12 14:25:37 +02006816 if (end-line == linesize-1 && *(end-1) != '\n') {
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006817 /* Check if we reached the limit and the last char is not \n.
6818 * Watch out for the last line without the terminating '\n'!
6819 */
William Lallemand64e84512015-05-12 14:25:37 +02006820 char *newline;
6821 int newlinesize = linesize * 2;
6822
6823 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
6824 if (newline == NULL) {
6825 Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
6826 file, linenum);
6827 err_code |= ERR_ALERT | ERR_FATAL;
6828 continue;
6829 }
6830
6831 readbytes = linesize - 1;
6832 linesize = newlinesize;
6833 thisline = newline;
6834 continue;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006835 }
6836
William Lallemand64e84512015-05-12 14:25:37 +02006837 readbytes = 0;
6838
Willy Tarreaubaaee002006-06-26 02:48:02 +02006839 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006840 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006841 line++;
William Lallemandf9873ba2015-05-05 17:37:14 +02006842
Willy Tarreaubaaee002006-06-26 02:48:02 +02006843 arg = 0;
6844 args[arg] = line;
6845
6846 while (*line && arg < MAX_LINE_ARGS) {
William Lallemandf9873ba2015-05-05 17:37:14 +02006847 if (*line == '"' && !squote) { /* double quote outside single quotes */
6848 if (dquote)
6849 dquote = 0;
6850 else
6851 dquote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02006852 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02006853 end--;
6854 }
6855 else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
6856 if (squote)
6857 squote = 0;
6858 else
6859 squote = 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 == '\\' && !squote) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006864 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
6865 * C equivalent value. Other combinations left unchanged (eg: \1).
6866 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006867 int skip = 0;
6868 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
6869 *line = line[1];
6870 skip = 1;
6871 }
6872 else if (line[1] == 'r') {
6873 *line = '\r';
6874 skip = 1;
William Lallemandf9873ba2015-05-05 17:37:14 +02006875 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006876 else if (line[1] == 'n') {
6877 *line = '\n';
6878 skip = 1;
6879 }
6880 else if (line[1] == 't') {
6881 *line = '\t';
6882 skip = 1;
6883 }
6884 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01006885 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006886 unsigned char hex1, hex2;
6887 hex1 = toupper(line[2]) - '0';
6888 hex2 = toupper(line[3]) - '0';
6889 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
6890 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
6891 *line = (hex1<<4) + hex2;
6892 skip = 3;
6893 }
6894 else {
6895 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006896 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006897 }
William Lallemandf9873ba2015-05-05 17:37:14 +02006898 } else if (line[1] == '"') {
6899 *line = '"';
6900 skip = 1;
6901 } else if (line[1] == '\'') {
6902 *line = '\'';
6903 skip = 1;
William Lallemandb2f07452015-05-12 14:27:13 +02006904 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
6905 *line = '$';
6906 skip = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006907 }
6908 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01006909 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006910 end -= skip;
6911 }
6912 line++;
6913 }
William Lallemandf9873ba2015-05-05 17:37:14 +02006914 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006915 /* end of string, end of loop */
6916 *line = 0;
6917 break;
6918 }
William Lallemandf9873ba2015-05-05 17:37:14 +02006919 else if (!squote && !dquote && isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006920 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006921 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006922 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006923 line++;
6924 args[++arg] = line;
6925 }
William Lallemandb2f07452015-05-12 14:27:13 +02006926 else if (dquote && *line == '$') {
6927 /* environment variables are evaluated inside double quotes */
6928 char *var_beg;
6929 char *var_end;
6930 char save_char;
6931 char *value;
6932 int val_len;
6933 int newlinesize;
6934 int braces = 0;
6935
6936 var_beg = line + 1;
6937 var_end = var_beg;
6938
6939 if (*var_beg == '{') {
6940 var_beg++;
6941 var_end++;
6942 braces = 1;
6943 }
6944
6945 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
6946 Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
6947 err_code |= ERR_ALERT | ERR_FATAL;
6948 goto next_line; /* skip current line */
6949 }
6950
6951 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
6952 var_end++;
6953
6954 save_char = *var_end;
6955 *var_end = '\0';
6956 value = getenv(var_beg);
6957 *var_end = save_char;
6958 val_len = value ? strlen(value) : 0;
6959
6960 if (braces) {
6961 if (*var_end == '}') {
6962 var_end++;
6963 braces = 0;
6964 } else {
6965 Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
6966 err_code |= ERR_ALERT | ERR_FATAL;
6967 goto next_line; /* skip current line */
6968 }
6969 }
6970
6971 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
6972
6973 /* if not enough space in thisline */
6974 if (newlinesize > linesize) {
6975 char *newline;
6976
6977 newline = realloc(thisline, newlinesize * sizeof(*thisline));
6978 if (newline == NULL) {
6979 Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
6980 err_code |= ERR_ALERT | ERR_FATAL;
6981 goto next_line; /* slip current line */
6982 }
6983 /* recompute pointers if realloc returns a new pointer */
6984 if (newline != thisline) {
6985 int i;
6986 int diff;
6987
6988 for (i = 0; i <= arg; i++) {
6989 diff = args[i] - thisline;
6990 args[i] = newline + diff;
6991 }
6992
6993 diff = var_end - thisline;
6994 var_end = newline + diff;
6995 diff = end - thisline;
6996 end = newline + diff;
6997 diff = line - thisline;
6998 line = newline + diff;
6999 thisline = newline;
7000 }
7001 linesize = newlinesize;
7002 }
7003
7004 /* insert value inside the line */
7005 memmove(line + val_len, var_end, end - var_end + 1);
7006 memcpy(line, value, val_len);
7007 end += val_len - (var_end - line);
7008 line += val_len;
7009 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007010 else {
7011 line++;
7012 }
7013 }
William Lallemandb2f07452015-05-12 14:27:13 +02007014
William Lallemandf9873ba2015-05-05 17:37:14 +02007015 if (dquote) {
7016 Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
7017 err_code |= ERR_ALERT | ERR_FATAL;
7018 }
7019
7020 if (squote) {
7021 Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
7022 err_code |= ERR_ALERT | ERR_FATAL;
7023 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007024
7025 /* empty line */
7026 if (!**args)
7027 continue;
7028
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007029 if (*line) {
7030 /* we had to stop due to too many args.
7031 * Let's terminate the string, print the offending part then cut the
7032 * last arg.
7033 */
7034 while (*line && *line != '#' && *line != '\n' && *line != '\r')
7035 line++;
7036 *line = '\0';
7037
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01007038 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01007039 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007040 err_code |= ERR_ALERT | ERR_FATAL;
7041 args[arg] = line;
7042 }
7043
Willy Tarreau540abe42007-05-02 20:50:16 +02007044 /* zero out remaining args and ensure that at least one entry
7045 * is zeroed out.
7046 */
7047 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007048 args[arg] = line;
7049 }
7050
Willy Tarreau3842f002009-06-14 11:39:52 +02007051 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007052 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02007053 char *tmp;
7054
Willy Tarreau3842f002009-06-14 11:39:52 +02007055 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02007056 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007057 for (arg=0; *args[arg+1]; arg++)
7058 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02007059 *tmp = '\0'; // fix the next arg to \0
7060 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007061 }
Willy Tarreau3842f002009-06-14 11:39:52 +02007062 else if (!strcmp(args[0], "default")) {
7063 kwm = KWM_DEF;
7064 for (arg=0; *args[arg+1]; arg++)
7065 args[arg] = args[arg+1]; // shift args after inversion
7066 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007067
William Lallemand0f99e342011-10-12 17:50:54 +02007068 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
7069 strcmp(args[0], "log") != 0) {
7070 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02007071 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007072 }
7073
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007074 /* detect section start */
7075 list_for_each_entry(ics, &sections, list) {
7076 if (strcmp(args[0], ics->section_name) == 0) {
7077 cursection = ics->section_name;
7078 cs = ics;
7079 break;
7080 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007081 }
7082
Willy Tarreaubaaee002006-06-26 02:48:02 +02007083 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007084 if (cs)
7085 err_code |= cs->section_parser(file, linenum, args, kwm);
7086 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007087 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007088 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007089 }
Willy Tarreau058e9072009-07-20 09:30:05 +02007090
7091 if (err_code & ERR_ABORT)
7092 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007093 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01007094 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02007095 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007096 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02007097 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007098}
7099
Willy Tarreau64ab6072014-09-16 12:17:36 +02007100/* This function propagates processes from frontend <from> to backend <to> so
7101 * that it is always guaranteed that a backend pointed to by a frontend is
7102 * bound to all of its processes. After that, if the target is a "listen"
7103 * instance, the function recursively descends the target's own targets along
Willy Tarreau98d04852015-05-26 12:18:29 +02007104 * default_backend and use_backend rules. Since the bits are
Willy Tarreau64ab6072014-09-16 12:17:36 +02007105 * checked first to ensure that <to> is already bound to all processes of
7106 * <from>, there is no risk of looping and we ensure to follow the shortest
7107 * path to the destination.
7108 *
7109 * It is possible to set <to> to NULL for the first call so that the function
7110 * takes care of visiting the initial frontend in <from>.
7111 *
7112 * It is important to note that the function relies on the fact that all names
7113 * have already been resolved.
7114 */
7115void propagate_processes(struct proxy *from, struct proxy *to)
7116{
7117 struct switching_rule *rule;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007118
7119 if (to) {
7120 /* check whether we need to go down */
7121 if (from->bind_proc &&
7122 (from->bind_proc & to->bind_proc) == from->bind_proc)
7123 return;
7124
7125 if (!from->bind_proc && !to->bind_proc)
7126 return;
7127
7128 to->bind_proc = from->bind_proc ?
7129 (to->bind_proc | from->bind_proc) : 0;
7130
7131 /* now propagate down */
7132 from = to;
7133 }
7134
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01007135 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02007136 return;
7137
Willy Tarreauf6b70012014-12-18 14:00:43 +01007138 if (from->state == PR_STSTOPPED)
7139 return;
7140
Willy Tarreau64ab6072014-09-16 12:17:36 +02007141 /* default_backend */
7142 if (from->defbe.be)
7143 propagate_processes(from, from->defbe.be);
7144
7145 /* use_backend */
7146 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02007147 if (rule->dynamic)
7148 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007149 to = rule->be.backend;
7150 propagate_processes(from, to);
7151 }
Willy Tarreau64ab6072014-09-16 12:17:36 +02007152}
7153
Willy Tarreaubb925012009-07-23 13:36:36 +02007154/*
7155 * Returns the error code, 0 if OK, or any combination of :
7156 * - ERR_ABORT: must abort ASAP
7157 * - ERR_FATAL: we can continue parsing but not start the service
7158 * - ERR_WARN: a warning has been emitted
7159 * - ERR_ALERT: an alert has been emitted
7160 * Only the two first ones can stop processing, the two others are just
7161 * indicators.
7162 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007163int check_config_validity()
7164{
7165 int cfgerr = 0;
7166 struct proxy *curproxy = NULL;
7167 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02007168 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007169 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007170 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007171
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007172 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007173 /*
7174 * Now, check for the integrity of all that we have collected.
7175 */
7176
7177 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02007178 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007179
Willy Tarreau193b8c62012-11-22 00:17:38 +01007180 if (!global.tune.max_http_hdr)
7181 global.tune.max_http_hdr = MAX_HTTP_HDR;
7182
7183 if (!global.tune.cookie_len)
7184 global.tune.cookie_len = CAPTURE_LEN;
7185
7186 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
7187
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007188 /* Post initialisation of the users and groups lists. */
7189 err_code = userlist_postinit();
7190 if (err_code != ERR_NONE)
7191 goto out;
7192
Willy Tarreau55bc0f82009-03-15 14:51:53 +01007193 /* first, we will invert the proxy list order */
7194 curproxy = NULL;
7195 while (proxy) {
7196 struct proxy *next;
7197
7198 next = proxy->next;
7199 proxy->next = curproxy;
7200 curproxy = proxy;
7201 if (!next)
7202 break;
7203 proxy = next;
7204 }
7205
Willy Tarreau419ead82014-09-16 13:41:21 +02007206 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007207 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007208 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01007209 struct sticking_rule *mrule;
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007210 struct act_rule *trule;
7211 struct act_rule *hrqrule;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007212 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01007213 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007214
Willy Tarreau050536d2012-10-04 08:47:34 +02007215 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007216 /* proxy ID not set, use automatic numbering with first
7217 * spare entry starting with next_pxid.
7218 */
7219 next_pxid = get_next_id(&used_proxy_id, next_pxid);
7220 curproxy->conf.id.key = curproxy->uuid = next_pxid;
7221 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007222 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007223 next_pxid++;
7224
Willy Tarreau55ea7572007-06-17 19:56:27 +02007225
Willy Tarreaubaaee002006-06-26 02:48:02 +02007226 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02007227 /* ensure we don't keep listeners uselessly bound */
7228 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02007229 free((void *)curproxy->table.peers.name);
7230 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007231 continue;
7232 }
7233
Willy Tarreau102df612014-05-07 23:56:38 +02007234 /* Check multi-process mode compatibility for the current proxy */
7235
7236 if (curproxy->bind_proc) {
7237 /* an explicit bind-process was specified, let's check how many
7238 * processes remain.
7239 */
David Carliere6c39412015-07-02 07:00:17 +00007240 nbproc = my_popcountl(curproxy->bind_proc);
Willy Tarreau102df612014-05-07 23:56:38 +02007241
7242 curproxy->bind_proc &= nbits(global.nbproc);
7243 if (!curproxy->bind_proc && nbproc == 1) {
7244 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);
7245 curproxy->bind_proc = 1;
7246 }
7247 else if (!curproxy->bind_proc && nbproc > 1) {
7248 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);
7249 curproxy->bind_proc = 0;
7250 }
7251 }
7252
Willy Tarreau3d209582014-05-09 17:06:11 +02007253 /* check and reduce the bind-proc of each listener */
7254 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7255 unsigned long mask;
7256
7257 if (!bind_conf->bind_proc)
7258 continue;
7259
7260 mask = nbits(global.nbproc);
7261 if (curproxy->bind_proc)
7262 mask &= curproxy->bind_proc;
7263 /* mask cannot be null here thanks to the previous checks */
7264
David Carliere6c39412015-07-02 07:00:17 +00007265 nbproc = my_popcountl(bind_conf->bind_proc);
Willy Tarreau3d209582014-05-09 17:06:11 +02007266 bind_conf->bind_proc &= mask;
7267
7268 if (!bind_conf->bind_proc && nbproc == 1) {
7269 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",
7270 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7271 bind_conf->bind_proc = mask & ~(mask - 1);
7272 }
7273 else if (!bind_conf->bind_proc && nbproc > 1) {
7274 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",
7275 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7276 bind_conf->bind_proc = 0;
7277 }
7278 }
7279
Willy Tarreauff01a212009-03-15 13:46:16 +01007280 switch (curproxy->mode) {
7281 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007282 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007283 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007284 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
7285 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007286 cfgerr++;
7287 }
7288
7289 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007290 Warning("config : servers will be ignored for %s '%s'.\n",
7291 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007292 break;
7293
7294 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007295 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007296 break;
7297
7298 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01007299 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01007300 break;
7301 }
7302
Willy Tarreauf3934b82015-08-11 11:36:45 +02007303 if ((curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->conf.listeners)) {
7304 Warning("config : %s '%s' has no 'bind' directive. Please declare it as a backend if this was intended.\n",
7305 proxy_type_str(curproxy), curproxy->id);
7306 err_code |= ERR_WARN;
7307 }
7308
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007309 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007310 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007311 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007312 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
7313 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007314 cfgerr++;
7315 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007316#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007317 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007318 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
7319 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007320 cfgerr++;
7321 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007322#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02007323 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007324 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
7325 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007326 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007327 }
7328 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02007329 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007330 /* If no LB algo is set in a backend, and we're not in
7331 * transparent mode, dispatch mode nor proxy mode, we
7332 * want to use balance roundrobin by default.
7333 */
7334 curproxy->lbprm.algo &= ~BE_LB_ALGO;
7335 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007336 }
7337 }
Willy Tarreau193cf932007-09-17 10:17:23 +02007338
Willy Tarreau1620ec32011-08-06 17:05:02 +02007339 if (curproxy->options & PR_O_DISPATCH)
7340 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
7341 else if (curproxy->options & PR_O_HTTP_PROXY)
7342 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
7343 else if (curproxy->options & PR_O_TRANSP)
7344 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01007345
Willy Tarreau1620ec32011-08-06 17:05:02 +02007346 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
7347 if (curproxy->options & PR_O_DISABLE404) {
7348 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7349 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
7350 err_code |= ERR_WARN;
7351 curproxy->options &= ~PR_O_DISABLE404;
7352 }
7353 if (curproxy->options2 & PR_O2_CHK_SNDST) {
7354 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7355 "send-state", proxy_type_str(curproxy), curproxy->id);
7356 err_code |= ERR_WARN;
7357 curproxy->options &= ~PR_O2_CHK_SNDST;
7358 }
Willy Tarreauef781042010-01-27 11:53:01 +01007359 }
7360
Simon Horman98637e52014-06-20 12:30:16 +09007361 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
7362 if (!global.external_check) {
7363 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
7364 curproxy->id, "option external-check");
7365 cfgerr++;
7366 }
7367 if (!curproxy->check_command) {
7368 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
7369 curproxy->id, "option external-check");
7370 cfgerr++;
7371 }
7372 }
7373
Simon Horman64e34162015-02-06 11:11:57 +09007374 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007375 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
7376 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Pieter Baauw8669e972015-08-17 00:45:05 +02007377 "'email-alert from', 'email-alert level' 'email-alert mailers', "
7378 "'email-alert myhostname', or 'email-alert to' "
7379 "requires each of 'email-alert from', 'email-alert mailers' and 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007380 "to be present).\n",
7381 proxy_type_str(curproxy), curproxy->id);
7382 err_code |= ERR_WARN;
7383 free_email_alert(curproxy);
7384 }
7385 if (!curproxy->email_alert.myhostname)
7386 curproxy->email_alert.myhostname = hostname;
Simon Horman9dc49962015-01-30 11:22:59 +09007387 }
7388
Simon Horman98637e52014-06-20 12:30:16 +09007389 if (curproxy->check_command) {
7390 int clear = 0;
7391 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7392 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7393 "external-check command", proxy_type_str(curproxy), curproxy->id);
7394 err_code |= ERR_WARN;
7395 clear = 1;
7396 }
7397 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
7398 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-command path' is not set.\n",
7399 curproxy->id, "external-check command");
7400 cfgerr++;
7401 }
7402 if (clear) {
7403 free(curproxy->check_command);
7404 curproxy->check_command = NULL;
7405 }
7406 }
7407
7408 if (curproxy->check_path) {
7409 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7410 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7411 "external-check path", proxy_type_str(curproxy), curproxy->id);
7412 err_code |= ERR_WARN;
7413 free(curproxy->check_path);
7414 curproxy->check_path = NULL;
7415 }
7416 }
7417
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007418 /* if a default backend was specified, let's find it */
7419 if (curproxy->defbe.name) {
7420 struct proxy *target;
7421
Willy Tarreauafb39922015-05-26 12:04:09 +02007422 target = proxy_be_by_name(curproxy->defbe.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007423 if (!target) {
7424 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
7425 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007426 cfgerr++;
7427 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007428 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
7429 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02007430 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007431 } else if (target->mode != curproxy->mode &&
7432 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7433
7434 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) as its default backend (see 'mode').\n",
7435 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7436 curproxy->conf.file, curproxy->conf.line,
7437 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7438 target->conf.file, target->conf.line);
7439 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007440 } else {
7441 free(curproxy->defbe.name);
7442 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01007443
7444 /* Emit a warning if this proxy also has some servers */
7445 if (curproxy->srv) {
7446 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
7447 curproxy->id);
7448 err_code |= ERR_WARN;
7449 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007450 }
7451 }
7452
Willy Tarreau55ea7572007-06-17 19:56:27 +02007453 /* find the target proxy for 'use_backend' rules */
7454 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007455 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007456 struct logformat_node *node;
7457 char *pxname;
7458
7459 /* Try to parse the string as a log format expression. If the result
7460 * of the parsing is only one entry containing a simple string, then
7461 * it's a standard string corresponding to a static rule, thus the
7462 * parsing is cancelled and be.name is restored to be resolved.
7463 */
7464 pxname = rule->be.name;
7465 LIST_INIT(&rule->be.expr);
7466 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
7467 curproxy->conf.args.file, curproxy->conf.args.line);
7468 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
7469
7470 if (!LIST_ISEMPTY(&rule->be.expr)) {
7471 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
7472 rule->dynamic = 1;
7473 free(pxname);
7474 continue;
7475 }
7476 /* simple string: free the expression and fall back to static rule */
7477 free(node->arg);
7478 free(node);
7479 }
7480
7481 rule->dynamic = 0;
7482 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007483
Willy Tarreauafb39922015-05-26 12:04:09 +02007484 target = proxy_be_by_name(rule->be.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007485 if (!target) {
7486 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
7487 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007488 cfgerr++;
7489 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007490 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
7491 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007492 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007493 } else if (target->mode != curproxy->mode &&
7494 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7495
7496 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) in a 'use_backend' rule (see 'mode').\n",
7497 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7498 curproxy->conf.file, curproxy->conf.line,
7499 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7500 target->conf.file, target->conf.line);
7501 cfgerr++;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007502 } else {
7503 free((void *)rule->be.name);
7504 rule->be.backend = target;
7505 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007506 }
7507
Willy Tarreau64ab6072014-09-16 12:17:36 +02007508 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007509 list_for_each_entry(srule, &curproxy->server_rules, list) {
7510 struct server *target = findserver(curproxy, srule->srv.name);
7511
7512 if (!target) {
7513 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7514 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7515 cfgerr++;
7516 continue;
7517 }
7518 free((void *)srule->srv.name);
7519 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007520 }
7521
Emeric Brunb982a3d2010-01-04 15:45:53 +01007522 /* find the target table for 'stick' rules */
7523 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7524 struct proxy *target;
7525
Emeric Brun1d33b292010-01-04 15:47:17 +01007526 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7527 if (mrule->flags & STK_IS_STORE)
7528 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7529
Emeric Brunb982a3d2010-01-04 15:45:53 +01007530 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007531 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007532 else
7533 target = curproxy;
7534
7535 if (!target) {
7536 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7537 curproxy->id, mrule->table.name);
7538 cfgerr++;
7539 }
7540 else if (target->table.size == 0) {
7541 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7542 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7543 cfgerr++;
7544 }
Willy Tarreau12785782012-04-27 21:37:17 +02007545 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7546 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007547 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7548 cfgerr++;
7549 }
7550 else {
7551 free((void *)mrule->table.name);
7552 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007553 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007554 }
7555 }
7556
7557 /* find the target table for 'store response' rules */
7558 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7559 struct proxy *target;
7560
Emeric Brun1d33b292010-01-04 15:47:17 +01007561 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7562
Emeric Brunb982a3d2010-01-04 15:45:53 +01007563 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007564 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007565 else
7566 target = curproxy;
7567
7568 if (!target) {
7569 Alert("Proxy '%s': unable to find store table '%s'.\n",
7570 curproxy->id, mrule->table.name);
7571 cfgerr++;
7572 }
7573 else if (target->table.size == 0) {
7574 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7575 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7576 cfgerr++;
7577 }
Willy Tarreau12785782012-04-27 21:37:17 +02007578 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7579 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007580 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7581 cfgerr++;
7582 }
7583 else {
7584 free((void *)mrule->table.name);
7585 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007586 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007587 }
7588 }
7589
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007590 /* find the target table for 'tcp-request' layer 4 rules */
7591 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
7592 struct proxy *target;
7593
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007594 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007595 continue;
7596
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007597 if (trule->arg.trk_ctr.table.n)
7598 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007599 else
7600 target = curproxy;
7601
7602 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007603 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007604 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007605 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007606 cfgerr++;
7607 }
7608 else if (target->table.size == 0) {
7609 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007610 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007611 cfgerr++;
7612 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007613 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007614 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007615 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007616 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007617 cfgerr++;
7618 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007619 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007620 free(trule->arg.trk_ctr.table.n);
7621 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007622 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007623 * to pass a list of counters to track and allocate them right here using
7624 * stktable_alloc_data_type().
7625 */
7626 }
7627 }
7628
Willy Tarreaud1f96522010-08-03 19:34:32 +02007629 /* find the target table for 'tcp-request' layer 6 rules */
7630 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7631 struct proxy *target;
7632
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007633 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02007634 continue;
7635
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007636 if (trule->arg.trk_ctr.table.n)
7637 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007638 else
7639 target = curproxy;
7640
7641 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007642 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007643 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007644 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02007645 cfgerr++;
7646 }
7647 else if (target->table.size == 0) {
7648 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007649 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007650 cfgerr++;
7651 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007652 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007653 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007654 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007655 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007656 cfgerr++;
7657 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02007658 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007659 free(trule->arg.trk_ctr.table.n);
7660 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007661 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02007662 * to pass a list of counters to track and allocate them right here using
7663 * stktable_alloc_data_type().
7664 */
7665 }
7666 }
7667
Willy Tarreau09448f72014-06-25 18:12:15 +02007668 /* find the target table for 'http-request' layer 7 rules */
7669 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7670 struct proxy *target;
7671
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007672 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau09448f72014-06-25 18:12:15 +02007673 continue;
7674
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007675 if (hrqrule->arg.trk_ctr.table.n)
7676 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
Willy Tarreau09448f72014-06-25 18:12:15 +02007677 else
7678 target = curproxy;
7679
7680 if (!target) {
7681 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007682 curproxy->id, hrqrule->arg.trk_ctr.table.n,
Willy Tarreau09448f72014-06-25 18:12:15 +02007683 http_req_trk_idx(hrqrule->action));
7684 cfgerr++;
7685 }
7686 else if (target->table.size == 0) {
7687 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007688 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau09448f72014-06-25 18:12:15 +02007689 cfgerr++;
7690 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007691 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau09448f72014-06-25 18:12:15 +02007692 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007693 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau09448f72014-06-25 18:12:15 +02007694 http_req_trk_idx(hrqrule->action));
7695 cfgerr++;
7696 }
7697 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007698 free(hrqrule->arg.trk_ctr.table.n);
7699 hrqrule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau09448f72014-06-25 18:12:15 +02007700 /* Note: if we decide to enhance the track-sc syntax, we may be able
7701 * to pass a list of counters to track and allocate them right here using
7702 * stktable_alloc_data_type().
7703 */
7704 }
7705 }
7706
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02007707 /* move any "block" rules at the beginning of the http-request rules */
7708 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
7709 /* insert block_rules into http_req_rules at the beginning */
7710 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
7711 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
7712 curproxy->block_rules.n->p = &curproxy->http_req_rules;
7713 curproxy->http_req_rules.n = curproxy->block_rules.n;
7714 LIST_INIT(&curproxy->block_rules);
7715 }
7716
Emeric Brun32da3c42010-09-23 18:39:19 +02007717 if (curproxy->table.peers.name) {
7718 struct peers *curpeers = peers;
7719
7720 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
7721 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
7722 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01007723 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02007724 break;
7725 }
7726 }
7727
7728 if (!curpeers) {
7729 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
7730 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007731 free((void *)curproxy->table.peers.name);
7732 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007733 cfgerr++;
7734 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02007735 else if (curpeers->state == PR_STSTOPPED) {
7736 /* silently disable this peers section */
7737 curproxy->table.peers.p = NULL;
7738 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007739 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02007740 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
7741 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007742 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007743 cfgerr++;
7744 }
7745 }
7746
Simon Horman9dc49962015-01-30 11:22:59 +09007747
7748 if (curproxy->email_alert.mailers.name) {
7749 struct mailers *curmailers = mailers;
7750
7751 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
7752 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
7753 free(curproxy->email_alert.mailers.name);
7754 curproxy->email_alert.mailers.m = curmailers;
7755 curmailers->users++;
7756 break;
7757 }
7758 }
7759
7760 if (!curmailers) {
7761 Alert("Proxy '%s': unable to find mailers '%s'.\n",
7762 curproxy->id, curproxy->email_alert.mailers.name);
7763 free_email_alert(curproxy);
7764 cfgerr++;
7765 }
7766 }
7767
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007768 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01007769 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007770 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
7771 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
7772 "proxy", curproxy->id);
7773 cfgerr++;
7774 goto out_uri_auth_compat;
7775 }
7776
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007777 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007778 const char *uri_auth_compat_req[10];
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007779 struct act_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01007780 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007781
Willy Tarreau95fa4692010-02-01 13:05:50 +01007782 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
7783 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007784
7785 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007786 uri_auth_compat_req[i++] = "realm";
7787 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
7788 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007789
Willy Tarreau95fa4692010-02-01 13:05:50 +01007790 uri_auth_compat_req[i++] = "unless";
7791 uri_auth_compat_req[i++] = "{";
7792 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
7793 uri_auth_compat_req[i++] = "}";
7794 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007795
Willy Tarreauff011f22011-01-06 17:51:27 +01007796 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
7797 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007798 cfgerr++;
7799 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007800 }
7801
Willy Tarreauff011f22011-01-06 17:51:27 +01007802 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01007803
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007804 if (curproxy->uri_auth->auth_realm) {
7805 free(curproxy->uri_auth->auth_realm);
7806 curproxy->uri_auth->auth_realm = NULL;
7807 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007808
7809 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007810 }
7811out_uri_auth_compat:
7812
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007813 /* compile the log format */
7814 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02007815 if (curproxy->conf.logformat_string != default_http_log_format &&
7816 curproxy->conf.logformat_string != default_tcp_log_format &&
7817 curproxy->conf.logformat_string != clf_http_log_format)
7818 free(curproxy->conf.logformat_string);
7819 curproxy->conf.logformat_string = NULL;
7820 free(curproxy->conf.lfs_file);
7821 curproxy->conf.lfs_file = NULL;
7822 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007823 }
7824
Willy Tarreau62a61232013-04-12 18:13:46 +02007825 if (curproxy->conf.logformat_string) {
7826 curproxy->conf.args.ctx = ARGC_LOG;
7827 curproxy->conf.args.file = curproxy->conf.lfs_file;
7828 curproxy->conf.args.line = curproxy->conf.lfs_line;
7829 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007830 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007831 curproxy->conf.args.file = NULL;
7832 curproxy->conf.args.line = 0;
7833 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007834
Willy Tarreau62a61232013-04-12 18:13:46 +02007835 if (curproxy->conf.uniqueid_format_string) {
7836 curproxy->conf.args.ctx = ARGC_UIF;
7837 curproxy->conf.args.file = curproxy->conf.uif_file;
7838 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01007839 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Godbachd9722032014-12-18 15:44:58 +08007840 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007841 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007842 curproxy->conf.args.file = NULL;
7843 curproxy->conf.args.line = 0;
7844 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007845
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007846 /* only now we can check if some args remain unresolved.
7847 * This must be done after the users and groups resolution.
7848 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007849 cfgerr += smp_resolve_args(curproxy);
7850 if (!cfgerr)
7851 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01007852
Willy Tarreau2738a142006-07-08 17:28:09 +02007853 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007854 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02007855 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02007856 (!curproxy->timeout.connect ||
7857 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007858 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02007859 " | While not properly invalid, you will certainly encounter various problems\n"
7860 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01007861 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007862 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007863 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02007864 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02007865
Willy Tarreau1fa31262007-12-03 00:36:16 +01007866 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
7867 * We must still support older configurations, so let's find out whether those
7868 * parameters have been set or must be copied from contimeouts.
7869 */
7870 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007871 if (!curproxy->timeout.tarpit ||
7872 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007873 /* tarpit timeout not set. We search in the following order:
7874 * default.tarpit, curr.connect, default.connect.
7875 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007876 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007877 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007878 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007879 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007880 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007881 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007882 }
7883 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007884 (!curproxy->timeout.queue ||
7885 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007886 /* queue timeout not set. We search in the following order:
7887 * default.queue, curr.connect, default.connect.
7888 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007889 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007890 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007891 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007892 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007893 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007894 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007895 }
7896 }
7897
Willy Tarreau1620ec32011-08-06 17:05:02 +02007898 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01007899 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
7900 curproxy->check_req = (char *)malloc(curproxy->check_len);
7901 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02007902 }
7903
Willy Tarreau215663d2014-06-13 18:30:23 +02007904 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
7905 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
7906 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
7907 proxy_type_str(curproxy), curproxy->id);
7908 err_code |= ERR_WARN;
7909 }
7910
Willy Tarreau193b8c62012-11-22 00:17:38 +01007911 /* ensure that cookie capture length is not too large */
7912 if (curproxy->capture_len >= global.tune.cookie_len) {
7913 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
7914 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
7915 err_code |= ERR_WARN;
7916 curproxy->capture_len = global.tune.cookie_len - 1;
7917 }
7918
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007919 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01007920 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02007921 curproxy->req_cap_pool = create_pool("ptrcap",
7922 curproxy->nb_req_cap * sizeof(char *),
7923 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01007924 }
7925
7926 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02007927 curproxy->rsp_cap_pool = create_pool("ptrcap",
7928 curproxy->nb_rsp_cap * sizeof(char *),
7929 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01007930 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007931
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02007932 switch (curproxy->load_server_state_from_file) {
7933 case PR_SRV_STATE_FILE_UNSPEC:
7934 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
7935 break;
7936 case PR_SRV_STATE_FILE_GLOBAL:
7937 if (!global.server_state_file) {
7938 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",
7939 curproxy->id);
7940 err_code |= ERR_WARN;
7941 }
7942 break;
7943 }
7944
Willy Tarreaubaaee002006-06-26 02:48:02 +02007945 /* first, we will invert the servers list order */
7946 newsrv = NULL;
7947 while (curproxy->srv) {
7948 struct server *next;
7949
7950 next = curproxy->srv->next;
7951 curproxy->srv->next = newsrv;
7952 newsrv = curproxy->srv;
7953 if (!next)
7954 break;
7955 curproxy->srv = next;
7956 }
7957
Willy Tarreau17edc812014-01-03 12:14:34 +01007958 /* Check that no server name conflicts. This causes trouble in the stats.
7959 * We only emit a warning for the first conflict affecting each server,
7960 * in order to avoid combinatory explosion if all servers have the same
7961 * name. We do that only for servers which do not have an explicit ID,
7962 * because these IDs were made also for distinguishing them and we don't
7963 * want to annoy people who correctly manage them.
7964 */
7965 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
7966 struct server *other_srv;
7967
7968 if (newsrv->puid)
7969 continue;
7970
7971 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
7972 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
7973 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
7974 newsrv->conf.file, newsrv->conf.line,
7975 proxy_type_str(curproxy), curproxy->id,
7976 newsrv->id, other_srv->conf.line);
7977 break;
7978 }
7979 }
7980 }
7981
Willy Tarreaudd701652010-05-25 23:03:02 +02007982 /* assign automatic UIDs to servers which don't have one yet */
7983 next_id = 1;
7984 newsrv = curproxy->srv;
7985 while (newsrv != NULL) {
7986 if (!newsrv->puid) {
7987 /* server ID not set, use automatic numbering with first
7988 * spare entry starting with next_svid.
7989 */
7990 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
7991 newsrv->conf.id.key = newsrv->puid = next_id;
7992 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
7993 }
7994 next_id++;
7995 newsrv = newsrv->next;
7996 }
7997
Willy Tarreau20697042007-11-15 23:26:18 +01007998 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01007999 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02008000
Willy Tarreau62c3be22012-01-20 13:12:32 +01008001 /*
8002 * If this server supports a maxconn parameter, it needs a dedicated
8003 * tasks to fill the emptied slots when a connection leaves.
8004 * Also, resolve deferred tracking dependency if needed.
8005 */
8006 newsrv = curproxy->srv;
8007 while (newsrv != NULL) {
8008 if (newsrv->minconn > newsrv->maxconn) {
8009 /* Only 'minconn' was specified, or it was higher than or equal
8010 * to 'maxconn'. Let's turn this into maxconn and clean it, as
8011 * this will avoid further useless expensive computations.
8012 */
8013 newsrv->maxconn = newsrv->minconn;
8014 } else if (newsrv->maxconn && !newsrv->minconn) {
8015 /* minconn was not specified, so we set it to maxconn */
8016 newsrv->minconn = newsrv->maxconn;
8017 }
8018
Emeric Brun01f8e2f2012-05-18 16:02:00 +02008019#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02008020 if (newsrv->use_ssl || newsrv->check.use_ssl)
8021 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02008022#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02008023
Willy Tarreau2f075e92013-12-03 11:11:34 +01008024 /* set the check type on the server */
8025 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
8026
Willy Tarreau62c3be22012-01-20 13:12:32 +01008027 if (newsrv->trackit) {
8028 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02008029 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008030 char *pname, *sname;
8031
8032 pname = newsrv->trackit;
8033 sname = strrchr(pname, '/');
8034
8035 if (sname)
8036 *sname++ = '\0';
8037 else {
8038 sname = pname;
8039 pname = NULL;
8040 }
8041
8042 if (pname) {
Willy Tarreau9e0bb102015-05-26 11:24:42 +02008043 px = proxy_be_by_name(pname);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008044 if (!px) {
8045 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
8046 proxy_type_str(curproxy), curproxy->id,
8047 newsrv->id, pname);
8048 cfgerr++;
8049 goto next_srv;
8050 }
8051 } else
8052 px = curproxy;
8053
8054 srv = findserver(px, sname);
8055 if (!srv) {
8056 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
8057 proxy_type_str(curproxy), curproxy->id,
8058 newsrv->id, sname);
8059 cfgerr++;
8060 goto next_srv;
8061 }
8062
Willy Tarreau32091232014-05-16 13:52:00 +02008063 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
8064 !(srv->agent.state & CHK_ST_CONFIGURED) &&
8065 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01008066 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02008067 "tracking as it does not have any check nor agent enabled.\n",
8068 proxy_type_str(curproxy), curproxy->id,
8069 newsrv->id, px->id, srv->id);
8070 cfgerr++;
8071 goto next_srv;
8072 }
8073
8074 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
8075
8076 if (loop) {
8077 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
8078 "belongs to a tracking chain looping back to %s/%s.\n",
8079 proxy_type_str(curproxy), curproxy->id,
8080 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008081 cfgerr++;
8082 goto next_srv;
8083 }
8084
8085 if (curproxy != px &&
8086 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
8087 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
8088 "tracking: disable-on-404 option inconsistency.\n",
8089 proxy_type_str(curproxy), curproxy->id,
8090 newsrv->id, px->id, srv->id);
8091 cfgerr++;
8092 goto next_srv;
8093 }
8094
8095 /* if the other server is forced disabled, we have to do the same here */
Willy Tarreau20125212014-05-13 19:44:56 +02008096 if (srv->admin & SRV_ADMF_MAINT) {
Willy Tarreaua0066dd2014-05-16 11:25:16 +02008097 newsrv->admin |= SRV_ADMF_IMAINT;
Willy Tarreau892337c2014-05-13 23:41:20 +02008098 newsrv->state = SRV_ST_STOPPED;
Simon Horman125d0992013-02-24 17:23:38 +09008099 newsrv->check.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008100 }
8101
8102 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01008103 newsrv->tracknext = srv->trackers;
8104 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008105
8106 free(newsrv->trackit);
8107 newsrv->trackit = NULL;
8108 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008109
8110 /*
8111 * resolve server's resolvers name and update the resolvers pointer
8112 * accordingly
8113 */
8114 if (newsrv->resolvers_id) {
8115 struct dns_resolvers *curr_resolvers;
8116 int found;
8117
8118 found = 0;
8119 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
8120 if (!strcmp(curr_resolvers->id, newsrv->resolvers_id)) {
8121 found = 1;
8122 break;
8123 }
8124 }
8125
8126 if (!found) {
8127 Alert("config : %s '%s', server '%s': unable to find required resolvers '%s'\n",
8128 proxy_type_str(curproxy), curproxy->id,
8129 newsrv->id, newsrv->resolvers_id);
8130 cfgerr++;
8131 } else {
8132 free(newsrv->resolvers_id);
8133 newsrv->resolvers_id = NULL;
8134 if (newsrv->resolution)
8135 newsrv->resolution->resolvers = curr_resolvers;
8136 }
8137 }
8138 else {
8139 /* if no resolvers section associated to this server
8140 * we can clean up the associated resolution structure
8141 */
8142 if (newsrv->resolution) {
8143 free(newsrv->resolution->hostname_dn);
8144 newsrv->resolution->hostname_dn = NULL;
8145 free(newsrv->resolution);
8146 newsrv->resolution = NULL;
8147 }
8148 }
8149
Willy Tarreau62c3be22012-01-20 13:12:32 +01008150 next_srv:
8151 newsrv = newsrv->next;
8152 }
8153
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008154 /* We have to initialize the server lookup mechanism depending
8155 * on what LB algorithm was choosen.
8156 */
8157
8158 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
8159 switch (curproxy->lbprm.algo & BE_LB_KIND) {
8160 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02008161 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
8162 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8163 init_server_map(curproxy);
8164 } else {
8165 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
8166 fwrr_init_server_groups(curproxy);
8167 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008168 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008169
Willy Tarreau3ebb1162012-02-13 16:57:44 +01008170 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01008171 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
8172 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
8173 fwlc_init_server_tree(curproxy);
8174 } else {
8175 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
8176 fas_init_server_tree(curproxy);
8177 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008178 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008179
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008180 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008181 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
8182 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
8183 chash_init_server_tree(curproxy);
8184 } else {
8185 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8186 init_server_map(curproxy);
8187 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008188 break;
8189 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02008190
8191 if (curproxy->options & PR_O_LOGASAP)
8192 curproxy->to_log &= ~LW_BYTES;
8193
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008194 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01008195 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008196 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
8197 proxy_type_str(curproxy), curproxy->id);
8198 err_code |= ERR_WARN;
8199 }
8200
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008201 if (curproxy->mode != PR_MODE_HTTP) {
8202 int optnum;
8203
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008204 if (curproxy->uri_auth) {
8205 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
8206 proxy_type_str(curproxy), curproxy->id);
8207 err_code |= ERR_WARN;
8208 curproxy->uri_auth = NULL;
8209 }
8210
Willy Tarreau87cf5142011-08-19 22:57:24 +02008211 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008212 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8213 "forwardfor", proxy_type_str(curproxy), curproxy->id);
8214 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02008215 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008216 }
8217
8218 if (curproxy->options & PR_O_ORGTO) {
8219 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8220 "originalto", proxy_type_str(curproxy), curproxy->id);
8221 err_code |= ERR_WARN;
8222 curproxy->options &= ~PR_O_ORGTO;
8223 }
8224
8225 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
8226 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
8227 (curproxy->cap & cfg_opts[optnum].cap) &&
8228 (curproxy->options & cfg_opts[optnum].val)) {
8229 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8230 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
8231 err_code |= ERR_WARN;
8232 curproxy->options &= ~cfg_opts[optnum].val;
8233 }
8234 }
8235
8236 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
8237 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
8238 (curproxy->cap & cfg_opts2[optnum].cap) &&
8239 (curproxy->options2 & cfg_opts2[optnum].val)) {
8240 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8241 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
8242 err_code |= ERR_WARN;
8243 curproxy->options2 &= ~cfg_opts2[optnum].val;
8244 }
8245 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008246
Willy Tarreau29fbe512015-08-20 19:35:14 +02008247#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008248 if (curproxy->conn_src.bind_hdr_occ) {
8249 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008250 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01008251 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008252 err_code |= ERR_WARN;
8253 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008254#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008255 }
8256
Willy Tarreaubaaee002006-06-26 02:48:02 +02008257 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01008258 * ensure that we're not cross-dressing a TCP server into HTTP.
8259 */
8260 newsrv = curproxy->srv;
8261 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01008262 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008263 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
8264 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008265 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01008266 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008267
Willy Tarreau0cec3312011-10-31 13:49:26 +01008268 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
8269 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
8270 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8271 err_code |= ERR_WARN;
8272 }
8273
Willy Tarreauc93cd162014-05-13 15:54:22 +02008274 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02008275 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
8276 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8277 err_code |= ERR_WARN;
8278 }
8279
Willy Tarreau29fbe512015-08-20 19:35:14 +02008280#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008281 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
8282 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008283 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 +01008284 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008285 err_code |= ERR_WARN;
8286 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008287#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01008288 newsrv = newsrv->next;
8289 }
8290
Willy Tarreaue42bd962014-09-16 16:21:19 +02008291 /* check if we have a frontend with "tcp-request content" looking at L7
8292 * with no inspect-delay
8293 */
8294 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
8295 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008296 if (trule->action == ACT_TCP_CAPTURE &&
Thierry FOURNIERd0d65ae2015-08-04 08:21:12 +02008297 !(trule->arg.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008298 break;
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008299 if ((trule->action >= ACT_ACTION_TRK_SC0 && trule->action <= ACT_ACTION_TRK_SCMAX) &&
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008300 !(trule->arg.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008301 break;
8302 }
8303
8304 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
8305 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
8306 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
8307 " This means that these rules will randomly find their contents. This can be fixed by"
8308 " setting the tcp-request inspect-delay.\n",
8309 proxy_type_str(curproxy), curproxy->id);
8310 err_code |= ERR_WARN;
8311 }
8312 }
8313
Willy Tarreauc1a21672009-08-16 22:37:44 +02008314 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02008315 if (!curproxy->accept)
8316 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02008317
Willy Tarreauc1a21672009-08-16 22:37:44 +02008318 if (curproxy->tcp_req.inspect_delay ||
8319 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02008320 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008321
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008322 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008323 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008324 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008325 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008326
8327 /* both TCP and HTTP must check switching rules */
8328 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
8329 }
8330
8331 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02008332 if (curproxy->tcp_req.inspect_delay ||
8333 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
8334 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
8335
Emeric Brun97679e72010-09-23 17:56:44 +02008336 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
8337 curproxy->be_rsp_ana |= AN_RES_INSPECT;
8338
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008339 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008340 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008341 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008342 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008343
8344 /* If the backend does requires RDP cookie persistence, we have to
8345 * enable the corresponding analyser.
8346 */
8347 if (curproxy->options2 & PR_O2_RDPC_PRST)
8348 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
8349 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008350 }
8351
8352 /***********************************************************/
8353 /* At this point, target names have already been resolved. */
8354 /***********************************************************/
8355
8356 /* Check multi-process mode compatibility */
8357
8358 if (global.nbproc > 1 && global.stats_fe) {
8359 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8360 unsigned long mask;
8361
8362 mask = nbits(global.nbproc);
8363 if (global.stats_fe->bind_proc)
8364 mask &= global.stats_fe->bind_proc;
8365
8366 if (bind_conf->bind_proc)
8367 mask &= bind_conf->bind_proc;
8368
8369 /* stop here if more than one process is used */
David Carliere6c39412015-07-02 07:00:17 +00008370 if (my_popcountl(mask) > 1)
Willy Tarreau419ead82014-09-16 13:41:21 +02008371 break;
8372 }
8373 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
8374 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");
8375 }
8376 }
8377
8378 /* Make each frontend inherit bind-process from its listeners when not specified. */
8379 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8380 if (curproxy->bind_proc)
8381 continue;
8382
8383 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8384 unsigned long mask;
8385
Willy Tarreaue428b082015-05-04 21:57:58 +02008386 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008387 curproxy->bind_proc |= mask;
8388 }
8389
8390 if (!curproxy->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008391 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008392 }
8393
8394 if (global.stats_fe) {
8395 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8396 unsigned long mask;
8397
Willy Tarreaue428b082015-05-04 21:57:58 +02008398 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008399 global.stats_fe->bind_proc |= mask;
8400 }
8401 if (!global.stats_fe->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008402 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008403 }
8404
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02008405 /* propagate bindings from frontends to backends. Don't do it if there
8406 * are any fatal errors as we must not call it with unresolved proxies.
8407 */
8408 if (!cfgerr) {
8409 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8410 if (curproxy->cap & PR_CAP_FE)
8411 propagate_processes(curproxy, NULL);
8412 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008413 }
8414
8415 /* Bind each unbound backend to all processes when not specified. */
8416 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8417 if (curproxy->bind_proc)
8418 continue;
Willy Tarreaue428b082015-05-04 21:57:58 +02008419 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008420 }
8421
8422 /*******************************************************/
8423 /* At this step, all proxies have a non-null bind_proc */
8424 /*******************************************************/
8425
8426 /* perform the final checks before creating tasks */
8427
8428 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8429 struct listener *listener;
8430 unsigned int next_id;
8431 int nbproc;
8432
David Carliere6c39412015-07-02 07:00:17 +00008433 nbproc = my_popcountl(curproxy->bind_proc & nbits(global.nbproc));
Willy Tarreauc1a21672009-08-16 22:37:44 +02008434
Emeric Brunc52962f2012-11-15 18:28:02 +01008435#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008436 /* Configure SSL for each bind line.
8437 * Note: if configuration fails at some point, the ->ctx member
8438 * remains NULL so that listeners can later detach.
8439 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008440 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008441 int alloc_ctx;
8442
Emeric Brunc52962f2012-11-15 18:28:02 +01008443 if (!bind_conf->is_ssl) {
8444 if (bind_conf->default_ctx) {
8445 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
8446 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
8447 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008448 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01008449 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008450 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02008451 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008452 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008453 cfgerr++;
8454 continue;
8455 }
8456
Emeric Brun8dc60392014-05-09 13:52:00 +02008457 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008458 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02008459 if (alloc_ctx == SHCTX_E_INIT_LOCK)
8460 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");
8461 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008462 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02008463 cfgerr++;
8464 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008465 }
8466
Emeric Brunfc0421f2012-09-07 17:30:07 +02008467 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008468 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008469
8470 /* initialize CA variables if the certificates generation is enabled */
8471 cfgerr += ssl_sock_load_ca(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008472 }
Emeric Brunc52962f2012-11-15 18:28:02 +01008473#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008474
Willy Tarreaue6b98942007-10-29 01:09:36 +01008475 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008476 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008477 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008478 if (!listener->luid) {
8479 /* listener ID not set, use automatic numbering with first
8480 * spare entry starting with next_luid.
8481 */
8482 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
8483 listener->conf.id.key = listener->luid = next_id;
8484 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008485 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01008486 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008487
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008488 /* enable separate counters */
8489 if (curproxy->options2 & PR_O2_SOCKSTAT) {
8490 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01008491 if (!listener->name)
8492 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008493 }
Willy Tarreau81796be2012-09-22 19:11:47 +02008494
Willy Tarreaue6b98942007-10-29 01:09:36 +01008495 if (curproxy->options & PR_O_TCP_NOLING)
8496 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02008497 if (!listener->maxconn)
8498 listener->maxconn = curproxy->maxconn;
8499 if (!listener->backlog)
8500 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01008501 if (!listener->maxaccept)
8502 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
8503
8504 /* we want to have an optimal behaviour on single process mode to
8505 * maximize the work at once, but in multi-process we want to keep
8506 * some fairness between processes, so we target half of the max
8507 * number of events to be balanced over all the processes the proxy
8508 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
8509 * used to disable the limit.
8510 */
8511 if (listener->maxaccept > 0) {
8512 if (nbproc > 1)
8513 listener->maxaccept = (listener->maxaccept + 1) / 2;
8514 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
8515 }
8516
Willy Tarreau9903f0e2015-04-04 18:50:31 +02008517 listener->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02008518 listener->handler = process_stream;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008519 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01008520 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01008521
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008522 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
8523 listener->options |= LI_O_TCP_RULES;
8524
Willy Tarreaude3041d2010-05-31 10:56:17 +02008525 if (curproxy->mon_mask.s_addr)
8526 listener->options |= LI_O_CHK_MONNET;
8527
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008528 /* smart accept mode is automatic in HTTP mode */
8529 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008530 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008531 !(curproxy->no_options2 & PR_O2_SMARTACC)))
8532 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01008533 }
8534
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008535 /* Release unused SSL configs */
8536 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8537 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008538 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008539#ifdef USE_OPENSSL
Christopher Faulet31af49d2015-06-09 17:29:50 +02008540 ssl_sock_free_ca(bind_conf);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008541 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008542 free(bind_conf->ca_file);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008543 free(bind_conf->ca_sign_file);
8544 free(bind_conf->ca_sign_pass);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008545 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02008546 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008547 free(bind_conf->crl_file);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008548 if(bind_conf->keys_ref) {
8549 free(bind_conf->keys_ref->filename);
8550 free(bind_conf->keys_ref->tlskeys);
8551 free(bind_conf->keys_ref);
8552 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008553#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008554 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008555
Willy Tarreau102df612014-05-07 23:56:38 +02008556 if (nbproc > 1) {
8557 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02008558 int count, maxproc = 0;
8559
8560 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
David Carliere6c39412015-07-02 07:00:17 +00008561 count = my_popcountl(bind_conf->bind_proc);
Willy Tarreaueb791e02014-09-16 15:11:04 +02008562 if (count > maxproc)
8563 maxproc = count;
8564 }
8565 /* backends have 0, frontends have 1 or more */
8566 if (maxproc != 1)
8567 Warning("Proxy '%s': in multi-process mode, stats will be"
8568 " limited to process assigned to the current request.\n",
8569 curproxy->id);
8570
Willy Tarreau102df612014-05-07 23:56:38 +02008571 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
8572 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
8573 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008574 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008575 }
Willy Tarreau102df612014-05-07 23:56:38 +02008576 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
8577 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
8578 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008579 }
8580 }
Willy Tarreau918ff602011-07-25 16:33:49 +02008581
8582 /* create the task associated with the proxy */
8583 curproxy->task = task_new();
8584 if (curproxy->task) {
8585 curproxy->task->context = curproxy;
8586 curproxy->task->process = manage_proxy;
8587 /* no need to queue, it will be done automatically if some
8588 * listener gets limited.
8589 */
8590 curproxy->task->expire = TICK_ETERNITY;
8591 } else {
8592 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
8593 curproxy->id);
8594 cfgerr++;
8595 }
Willy Tarreaub369a042014-09-16 13:21:03 +02008596 }
8597
Willy Tarreaufbb78422011-06-05 15:38:35 +02008598 /* automatically compute fullconn if not set. We must not do it in the
8599 * loop above because cross-references are not yet fully resolved.
8600 */
8601 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8602 /* If <fullconn> is not set, let's set it to 10% of the sum of
8603 * the possible incoming frontend's maxconns.
8604 */
8605 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
8606 struct proxy *fe;
8607 int total = 0;
8608
8609 /* sum up the number of maxconns of frontends which
8610 * reference this backend at least once or which are
8611 * the same one ('listen').
8612 */
8613 for (fe = proxy; fe; fe = fe->next) {
8614 struct switching_rule *rule;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008615 int found = 0;
8616
8617 if (!(fe->cap & PR_CAP_FE))
8618 continue;
8619
8620 if (fe == curproxy) /* we're on a "listen" instance */
8621 found = 1;
8622
8623 if (fe->defbe.be == curproxy) /* "default_backend" */
8624 found = 1;
8625
8626 /* check if a "use_backend" rule matches */
8627 if (!found) {
8628 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01008629 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02008630 found = 1;
8631 break;
8632 }
8633 }
8634 }
8635
Willy Tarreaufbb78422011-06-05 15:38:35 +02008636 /* now we've checked all possible ways to reference a backend
8637 * from a frontend.
8638 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02008639 if (!found)
8640 continue;
8641 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008642 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02008643 /* we have the sum of the maxconns in <total>. We only
8644 * keep 10% of that sum to set the default fullconn, with
8645 * a hard minimum of 1 (to avoid a divide by zero).
8646 */
8647 curproxy->fullconn = (total + 9) / 10;
8648 if (!curproxy->fullconn)
8649 curproxy->fullconn = 1;
8650 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01008651 }
8652
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008653 /*
8654 * Recount currently required checks.
8655 */
8656
8657 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
8658 int optnum;
8659
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008660 for (optnum = 0; cfg_opts[optnum].name; optnum++)
8661 if (curproxy->options & cfg_opts[optnum].val)
8662 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008663
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008664 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
8665 if (curproxy->options2 & cfg_opts2[optnum].val)
8666 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008667 }
8668
Willy Tarreau0fca4832015-05-01 19:12:05 +02008669 /* compute the required process bindings for the peers */
8670 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
8671 if (curproxy->table.peers.p)
8672 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
8673
Willy Tarreau122541c2011-09-07 21:24:49 +02008674 if (peers) {
8675 struct peers *curpeers = peers, **last;
8676 struct peer *p, *pb;
8677
Willy Tarreau1e273012015-05-01 19:15:17 +02008678 /* Remove all peers sections which don't have a valid listener,
8679 * which are not used by any table, or which are bound to more
8680 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02008681 */
8682 last = &peers;
8683 while (*last) {
8684 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008685
8686 if (curpeers->state == PR_STSTOPPED) {
8687 /* the "disabled" keyword was present */
8688 if (curpeers->peers_fe)
8689 stop_proxy(curpeers->peers_fe);
8690 curpeers->peers_fe = NULL;
8691 }
8692 else if (!curpeers->peers_fe) {
8693 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
8694 curpeers->id, localpeer);
8695 }
David Carliere6c39412015-07-02 07:00:17 +00008696 else if (my_popcountl(curpeers->peers_fe->bind_proc) != 1) {
Willy Tarreau1e273012015-05-01 19:15:17 +02008697 /* either it's totally stopped or too much used */
8698 if (curpeers->peers_fe->bind_proc) {
8699 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreau64c57222015-05-04 21:48:51 +02008700 "running in different processes (%d different ones). "
8701 "Check global.nbproc and all tables' bind-process "
David Carliere6c39412015-07-02 07:00:17 +00008702 "settings.\n", curpeers->id, my_popcountl(curpeers->peers_fe->bind_proc));
Willy Tarreau1e273012015-05-01 19:15:17 +02008703 cfgerr++;
8704 }
8705 stop_proxy(curpeers->peers_fe);
8706 curpeers->peers_fe = NULL;
8707 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008708 else {
Emeric Brunb3971ab2015-05-12 18:49:09 +02008709 peers_init_sync(curpeers);
Willy Tarreau122541c2011-09-07 21:24:49 +02008710 last = &curpeers->next;
8711 continue;
8712 }
8713
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008714 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02008715 p = curpeers->remote;
8716 while (p) {
8717 pb = p->next;
8718 free(p->id);
8719 free(p);
8720 p = pb;
8721 }
8722
8723 /* Destroy and unlink this curpeers section.
8724 * Note: curpeers is backed up into *last.
8725 */
8726 free(curpeers->id);
8727 curpeers = curpeers->next;
8728 free(*last);
8729 *last = curpeers;
8730 }
8731 }
8732
Willy Tarreau6866f3f2015-05-01 19:09:08 +02008733 /* initialize stick-tables on backend capable proxies. This must not
8734 * be done earlier because the data size may be discovered while parsing
8735 * other proxies.
8736 */
8737 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8738 if (curproxy->state == PR_STSTOPPED)
8739 continue;
8740
8741 if (!stktable_init(&curproxy->table)) {
8742 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
8743 cfgerr++;
8744 }
8745 }
8746
Simon Horman0d16a402015-01-30 11:22:58 +09008747 if (mailers) {
8748 struct mailers *curmailers = mailers, **last;
8749 struct mailer *m, *mb;
8750
8751 /* Remove all mailers sections which don't have a valid listener.
8752 * This can happen when a mailers section is never referenced.
8753 */
8754 last = &mailers;
8755 while (*last) {
8756 curmailers = *last;
8757 if (curmailers->users) {
8758 last = &curmailers->next;
8759 continue;
8760 }
8761
8762 Warning("Removing incomplete section 'mailers %s'.\n",
8763 curmailers->id);
8764
8765 m = curmailers->mailer_list;
8766 while (m) {
8767 mb = m->next;
8768 free(m->id);
8769 free(m);
8770 m = mb;
8771 }
8772
8773 /* Destroy and unlink this curmailers section.
8774 * Note: curmailers is backed up into *last.
8775 */
8776 free(curmailers->id);
8777 curmailers = curmailers->next;
8778 free(*last);
8779 *last = curmailers;
8780 }
8781 }
8782
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02008783 /* Update server_state_file_name to backend name if backend is supposed to use
8784 * a server-state file locally defined and none has been provided */
8785 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8786 if (curproxy->load_server_state_from_file == PR_SRV_STATE_FILE_LOCAL &&
8787 curproxy->server_state_file_name == NULL)
8788 curproxy->server_state_file_name = strdup(curproxy->id);
8789 }
8790
Willy Tarreau34eb6712011-10-24 18:15:04 +02008791 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02008792 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02008793 MEM_F_SHARED);
8794
Willy Tarreaubb925012009-07-23 13:36:36 +02008795 if (cfgerr > 0)
8796 err_code |= ERR_ALERT | ERR_FATAL;
8797 out:
8798 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02008799}
8800
Willy Tarreau5b2c3362008-07-09 19:39:06 +02008801/*
8802 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
8803 * parsing sessions.
8804 */
8805void cfg_register_keywords(struct cfg_kw_list *kwl)
8806{
8807 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
8808}
Willy Tarreaubaaee002006-06-26 02:48:02 +02008809
Willy Tarreau5b2c3362008-07-09 19:39:06 +02008810/*
8811 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
8812 */
8813void cfg_unregister_keywords(struct cfg_kw_list *kwl)
8814{
8815 LIST_DEL(&kwl->list);
8816 LIST_INIT(&kwl->list);
8817}
Willy Tarreaubaaee002006-06-26 02:48:02 +02008818
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01008819/* this function register new section in the haproxy configuration file.
8820 * <section_name> is the name of this new section and <section_parser>
8821 * is the called parser. If two section declaration have the same name,
8822 * only the first declared is used.
8823 */
8824int cfg_register_section(char *section_name,
8825 int (*section_parser)(const char *, int, char **, int))
8826{
8827 struct cfg_section *cs;
8828
8829 cs = calloc(1, sizeof(*cs));
8830 if (!cs) {
8831 Alert("register section '%s': out of memory.\n", section_name);
8832 return 0;
8833 }
8834
8835 cs->section_name = section_name;
8836 cs->section_parser = section_parser;
8837
8838 LIST_ADDQ(&sections, &cs->list);
8839
8840 return 1;
8841}
8842
Willy Tarreaubaaee002006-06-26 02:48:02 +02008843/*
8844 * Local variables:
8845 * c-indent-level: 8
8846 * c-basic-offset: 8
8847 * End:
8848 */