blob: 610e165bab52b8c0629033d7183db3bb17573283 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreauff011f22011-01-06 17:51:27 +01004 * Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
Cyril Bonté1a0191d2014-08-29 20:20:02 +020013#ifdef CONFIG_HAP_CRYPT
14/* This is to have crypt() defined on Linux */
15#define _GNU_SOURCE
16
17#ifdef NEED_CRYPT_H
18/* some platforms such as Solaris need this */
19#include <crypt.h>
20#endif
21#endif /* CONFIG_HAP_CRYPT */
22
Willy Tarreaubaaee002006-06-26 02:48:02 +020023#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <netdb.h>
27#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020028#include <pwd.h>
29#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020030#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020031#include <sys/types.h>
32#include <sys/stat.h>
33#include <fcntl.h>
34#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
Willy Tarreau2dd0d472006-06-29 17:53:05 +020036#include <common/cfgparse.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020037#include <common/chunk.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020038#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020039#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020040#include <common/memory.h>
41#include <common/standard.h>
42#include <common/time.h>
43#include <common/uri_auth.h>
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +010044#include <common/namespace.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020045
46#include <types/capture.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020047#include <types/compression.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020048#include <types/global.h>
Willy Tarreau3fdb3662012-11-12 00:42:33 +010049#include <types/obj_type.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020050#include <types/peers.h>
Simon Horman0d16a402015-01-30 11:22:58 +090051#include <types/mailers.h>
Baptiste Assmann325137d2015-04-13 23:40:55 +020052#include <types/dns.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020053
Willy Tarreaueb0c6142007-05-07 00:53:22 +020054#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010055#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020056#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020057#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020058#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020059#include <proto/compression.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020060#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020061#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020062#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020063#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010064#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020065#include <proto/lb_fwlc.h>
66#include <proto/lb_fwrr.h>
67#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020068#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020069#include <proto/log.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020070#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010071#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020072#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010073#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010074#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020075#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020076#include <proto/sample.h>
Willy Tarreau9903f0e2015-04-04 18:50:31 +020077#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020078#include <proto/server.h>
Willy Tarreau87b09662015-04-03 00:22:06 +020079#include <proto/stream.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020080#include <proto/raw_sock.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020081#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010082#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020083
Emeric Brunfc0421f2012-09-07 17:30:07 +020084#ifdef USE_OPENSSL
85#include <types/ssl_sock.h>
86#include <proto/ssl_sock.h>
87#include <proto/shctx.h>
88#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020089
Willy Tarreauf3c69202006-07-09 16:42:34 +020090/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
91 * ssl-hello-chk option to ensure that the remote server speaks SSL.
92 *
93 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
94 */
95const char sslv3_client_hello_pkt[] = {
96 "\x16" /* ContentType : 0x16 = Hanshake */
97 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
98 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
99 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
100 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
101 "\x03\x00" /* Hello Version : 0x0300 = v3 */
102 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
103 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
104 "\x00" /* Session ID length : empty (no session ID) */
105 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
106 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
107 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
108 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
109 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
110 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
111 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
112 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
113 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
114 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
115 "\x00\x38" "\x00\x39" "\x00\x3A"
116 "\x01" /* Compression Length : 0x01 = 1 byte for types */
117 "\x00" /* Compression Type : 0x00 = NULL compression */
118};
119
Willy Tarreau3842f002009-06-14 11:39:52 +0200120/* various keyword modifiers */
121enum kw_mod {
122 KWM_STD = 0, /* normal */
123 KWM_NO, /* "no" prefixed before the keyword */
124 KWM_DEF, /* "default" prefixed before the keyword */
125};
126
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +0100127/* permit to store configuration section */
128struct cfg_section {
129 struct list list;
130 char *section_name;
131 int (*section_parser)(const char *, int, char **, int);
132};
133
134/* Used to chain configuration sections definitions. This list
135 * stores struct cfg_section
136 */
137struct list sections = LIST_HEAD_INIT(sections);
138
Willy Tarreau13943ab2006-12-31 00:24:10 +0100139/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100140struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100141 const char *name;
142 unsigned int val;
143 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100144 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100145 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100146};
147
148/* proxy->options */
149static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100150{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100151 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
152 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
153 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
154 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
155 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
156 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100157 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau9fbe18e2015-05-01 22:42:08 +0200158 { "http-buffer-request", PR_O_WREQ_BODY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau0f228a02015-05-01 15:37:53 +0200159 { "http-ignore-probes", PR_O_IGNORE_PRB, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreau9420b122013-12-15 18:58:25 +0100160 { "prefer-last-server", PR_O_PREF_LAST, PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100161 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
162 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
163 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100164 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100165#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100166 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100167#else
168 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100169#endif
170
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100171 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100172};
173
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100174/* proxy->options2 */
175static const struct cfg_opt cfg_opts2[] =
176{
177#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100178 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
179 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
180 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100181#else
182 { "splice-request", 0, 0, 0, 0 },
183 { "splice-response", 0, 0, 0, 0 },
184 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100185#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100186 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
187 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
188 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
189 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
190 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
191 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
192 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
193 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
194 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400195 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100196 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200197 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200198 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100199 { NULL, 0, 0, 0 }
200};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200201
Willy Tarreau6daf3432008-01-22 16:44:08 +0100202static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200203static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
204int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100205int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200206
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200207/* List head of all known configuration keywords */
208static struct cfg_kw_list cfg_keywords = {
209 .list = LIST_HEAD_INIT(cfg_keywords.list)
210};
211
Willy Tarreaubaaee002006-06-26 02:48:02 +0200212/*
213 * converts <str> to a list of listeners which are dynamically allocated.
214 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
215 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
216 * - <port> is a numerical port from 1 to 65535 ;
217 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
218 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200219 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
220 * not NULL, it must be a valid pointer to either NULL or a freeable area that
221 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200222 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200223int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf, const char *file, int line, char **err)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200224{
225 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100226 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200227 int port, end;
228
229 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200230
Willy Tarreaubaaee002006-06-26 02:48:02 +0200231 while (next && *next) {
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100232 struct sockaddr_storage ss, *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100233 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200234
235 str = next;
236 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100237 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200238 *next++ = 0;
239 }
240
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100241 ss2 = str2sa_range(str, &port, &end, err,
Willy Tarreau72b8c1f2015-09-08 15:50:19 +0200242 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix,
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +0200243 NULL, 1);
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100244 if (!ss2)
245 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200246
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100247 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100248 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200249 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100250 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200251 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200252
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100253 if (!port || !end) {
254 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
255 goto fail;
256 }
257
Emeric Bruned760922010-10-22 17:59:25 +0200258 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200259 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200260 goto fail;
261 }
262
263 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200264 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200265 goto fail;
266 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200267 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100268 else if (ss2->ss_family == AF_UNSPEC) {
269 socklen_t addr_len;
270
271 /* We want to attach to an already bound fd whose number
272 * is in the addr part of ss2 when cast to sockaddr_in.
273 * Note that by definition there is a single listener.
274 * We still have to determine the address family to
275 * register the correct protocol.
276 */
277 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
278 addr_len = sizeof(*ss2);
279 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
280 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
281 goto fail;
282 }
283
284 port = end = get_host_port(ss2);
285 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200286
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100287 /* OK the address looks correct */
288 ss = *ss2;
289
Willy Tarreaubaaee002006-06-26 02:48:02 +0200290 for (; port <= end; port++) {
291 l = (struct listener *)calloc(1, sizeof(struct listener));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100292 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200293 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
294 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
295 l->frontend = curproxy;
296 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200297
Willy Tarreau40aa0702013-03-10 23:51:38 +0100298 l->fd = fd;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200299 l->addr = ss;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200300 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100301 l->state = LI_INIT;
302
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100303 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200304 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100305 tcpv4_add_listener(l);
306 }
Emeric Bruned760922010-10-22 17:59:25 +0200307 else if (ss.ss_family == AF_INET6) {
308 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
309 tcpv6_add_listener(l);
310 }
311 else {
Emeric Bruned760922010-10-22 17:59:25 +0200312 uxst_add_listener(l);
313 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200314
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200315 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100316 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200317 } /* end for(port) */
318 } /* end while(next) */
319 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200320 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200321 fail:
322 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200323 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200324}
325
William Lallemand6e62fb62015-04-28 16:55:23 +0200326/*
327 * Report a fatal Alert when there is too much arguments
328 * The index is the current keyword in args
329 * Return 0 if the number of argument is correct, otherwise emit an alert and return 1
330 * Fill err_code with an ERR_ALERT and an ERR_FATAL
331 */
332int alertif_too_many_args_idx(int maxarg, int index, const char *file, int linenum, char **args, int *err_code)
333{
334 char *kw = NULL;
335 int i;
336
337 if (!*args[index + maxarg + 1])
338 return 0;
339
340 memprintf(&kw, "%s", args[0]);
341 for (i = 1; i <= index; i++) {
342 memprintf(&kw, "%s %s", kw, args[i]);
343 }
344
345 Alert("parsing [%s:%d] : '%s' cannot handle unexpected argument '%s'.\n", file, linenum, kw, args[index + maxarg + 1]);
346 free(kw);
347 *err_code |= ERR_ALERT | ERR_FATAL;
348 return 1;
349}
350
351/*
352 * same as alertif_too_many_args_idx with a 0 index
353 */
354int alertif_too_many_args(int maxarg, const char *file, int linenum, char **args, int *err_code)
355{
356 return alertif_too_many_args_idx(maxarg, 0, file, linenum, args, err_code);
357}
358
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200359/* Report a warning if a rule is placed after a 'tcp-request content' rule.
360 * Return 1 if the warning has been emitted, otherwise 0.
361 */
362int warnif_rule_after_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
363{
364 if (!LIST_ISEMPTY(&proxy->tcp_req.inspect_rules)) {
365 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request content' rule will still be processed before.\n",
366 file, line, arg);
367 return 1;
368 }
369 return 0;
370}
371
Willy Tarreau61d18892009-03-31 10:49:21 +0200372/* Report a warning if a rule is placed after a 'block' rule.
373 * Return 1 if the warning has been emitted, otherwise 0.
374 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100375int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200376{
Willy Tarreau353bc9f2014-04-28 22:05:31 +0200377 if (!LIST_ISEMPTY(&proxy->block_rules)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200378 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
379 file, line, arg);
380 return 1;
381 }
382 return 0;
383}
384
Willy Tarreau5002f572014-04-23 01:32:02 +0200385/* Report a warning if a rule is placed after an 'http_request' rule.
386 * Return 1 if the warning has been emitted, otherwise 0.
387 */
388int warnif_rule_after_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
389{
390 if (!LIST_ISEMPTY(&proxy->http_req_rules)) {
391 Warning("parsing [%s:%d] : a '%s' rule placed after an 'http-request' rule will still be processed before.\n",
392 file, line, arg);
393 return 1;
394 }
395 return 0;
396}
397
Willy Tarreau61d18892009-03-31 10:49:21 +0200398/* Report a warning if a rule is placed after a reqrewrite rule.
399 * Return 1 if the warning has been emitted, otherwise 0.
400 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100401int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200402{
403 if (proxy->req_exp) {
404 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
405 file, line, arg);
406 return 1;
407 }
408 return 0;
409}
410
411/* Report a warning if a rule is placed after a reqadd rule.
412 * Return 1 if the warning has been emitted, otherwise 0.
413 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100414int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200415{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100416 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200417 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
418 file, line, arg);
419 return 1;
420 }
421 return 0;
422}
423
424/* Report a warning if a rule is placed after a redirect rule.
425 * Return 1 if the warning has been emitted, otherwise 0.
426 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100427int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200428{
429 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
430 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
431 file, line, arg);
432 return 1;
433 }
434 return 0;
435}
436
437/* Report a warning if a rule is placed after a 'use_backend' rule.
438 * Return 1 if the warning has been emitted, otherwise 0.
439 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100440int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200441{
442 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
443 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
444 file, line, arg);
445 return 1;
446 }
447 return 0;
448}
449
Willy Tarreauee445d92014-04-23 01:39:04 +0200450/* Report a warning if a rule is placed after a 'use-server' rule.
451 * Return 1 if the warning has been emitted, otherwise 0.
452 */
453int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line, const char *arg)
454{
455 if (!LIST_ISEMPTY(&proxy->server_rules)) {
456 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use-server' rule will still be processed before.\n",
457 file, line, arg);
458 return 1;
459 }
460 return 0;
461}
462
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200463/* report a warning if a "tcp request connection" rule is dangerously placed */
464int warnif_misplaced_tcp_conn(struct proxy *proxy, const char *file, int line, const char *arg)
465{
466 return warnif_rule_after_tcp_cont(proxy, file, line, arg) ||
467 warnif_rule_after_block(proxy, file, line, arg) ||
468 warnif_rule_after_http_req(proxy, file, line, arg) ||
469 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
470 warnif_rule_after_reqadd(proxy, file, line, arg) ||
471 warnif_rule_after_redirect(proxy, file, line, arg) ||
472 warnif_rule_after_use_backend(proxy, file, line, arg) ||
473 warnif_rule_after_use_server(proxy, file, line, arg);
474}
475
476/* report a warning if a "tcp request content" rule is dangerously placed */
477int warnif_misplaced_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
478{
479 return warnif_rule_after_block(proxy, file, line, arg) ||
480 warnif_rule_after_http_req(proxy, file, line, arg) ||
481 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
482 warnif_rule_after_reqadd(proxy, file, line, arg) ||
483 warnif_rule_after_redirect(proxy, file, line, arg) ||
484 warnif_rule_after_use_backend(proxy, file, line, arg) ||
485 warnif_rule_after_use_server(proxy, file, line, arg);
486}
487
Willy Tarreau61d18892009-03-31 10:49:21 +0200488/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100489int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200490{
Willy Tarreau5002f572014-04-23 01:32:02 +0200491 return warnif_rule_after_http_req(proxy, file, line, arg) ||
492 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
493 warnif_rule_after_reqadd(proxy, file, line, arg) ||
494 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200495 warnif_rule_after_use_backend(proxy, file, line, arg) ||
496 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau5002f572014-04-23 01:32:02 +0200497}
498
499/* report a warning if an http-request rule is dangerously placed */
500int warnif_misplaced_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
501{
Willy Tarreau61d18892009-03-31 10:49:21 +0200502 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
503 warnif_rule_after_reqadd(proxy, file, line, arg) ||
504 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200505 warnif_rule_after_use_backend(proxy, file, line, arg) ||
506 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200507}
508
509/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100510int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200511{
512 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
513 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200514 warnif_rule_after_use_backend(proxy, file, line, arg) ||
515 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200516}
517
518/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100519int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200520{
521 return warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200522 warnif_rule_after_use_backend(proxy, file, line, arg) ||
523 warnif_rule_after_use_server(proxy, file, line, arg);
524}
525
526/* report a warning if a redirect rule is dangerously placed */
527int warnif_misplaced_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
528{
529 return warnif_rule_after_use_backend(proxy, file, line, arg) ||
530 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200531}
532
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100533/* Report it if a request ACL condition uses some keywords that are incompatible
534 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
535 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
536 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100537 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100538static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100539{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100540 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200541 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100542
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100543 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100544 return 0;
545
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100546 acl = acl_cond_conflicts(cond, where);
547 if (acl) {
548 if (acl->name && *acl->name)
549 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
550 file, line, acl->name, sample_ckp_names(where));
551 else
552 Warning("parsing [%s:%d] : anonymous acl will never match because it uses keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200553 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100554 return ERR_WARN;
555 }
556 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100557 return 0;
558
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100559 if (acl->name && *acl->name)
560 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200561 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100562 else
563 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200564 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100565 return ERR_WARN;
566}
567
Willy Tarreaubaaee002006-06-26 02:48:02 +0200568/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200569 * parse a line in a <global> section. Returns the error code, 0 if OK, or
570 * any combination of :
571 * - ERR_ABORT: must abort ASAP
572 * - ERR_FATAL: we can continue parsing but not start the service
573 * - ERR_WARN: a warning has been emitted
574 * - ERR_ALERT: an alert has been emitted
575 * Only the two first ones can stop processing, the two others are just
576 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200577 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200578int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200579{
Willy Tarreau058e9072009-07-20 09:30:05 +0200580 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200581 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200582
583 if (!strcmp(args[0], "global")) { /* new section */
584 /* no option, nothing special to do */
William Lallemand6e62fb62015-04-28 16:55:23 +0200585 alertif_too_many_args(0, file, linenum, args, &err_code);
Willy Tarreau058e9072009-07-20 09:30:05 +0200586 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200587 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200588 else if (!strcmp(args[0], "ca-base")) {
589#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +0200590 if(alertif_too_many_args(1, file, linenum, args, &err_code))
591 goto out;
Emeric Brunc8e8d122012-10-02 18:42:10 +0200592 if (global.ca_base != NULL) {
593 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
594 err_code |= ERR_ALERT;
595 goto out;
596 }
597 if (*(args[1]) == 0) {
598 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
599 err_code |= ERR_ALERT | ERR_FATAL;
600 goto out;
601 }
602 global.ca_base = strdup(args[1]);
603#else
604 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
605 err_code |= ERR_ALERT | ERR_FATAL;
606 goto out;
607#endif
608 }
609 else if (!strcmp(args[0], "crt-base")) {
610#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +0200611 if (alertif_too_many_args(1, file, linenum, args, &err_code))
612 goto out;
Emeric Brunc8e8d122012-10-02 18:42:10 +0200613 if (global.crt_base != NULL) {
614 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
615 err_code |= ERR_ALERT;
616 goto out;
617 }
618 if (*(args[1]) == 0) {
619 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
620 err_code |= ERR_ALERT | ERR_FATAL;
621 goto out;
622 }
623 global.crt_base = strdup(args[1]);
624#else
625 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
626 err_code |= ERR_ALERT | ERR_FATAL;
627 goto out;
628#endif
629 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200630 else if (!strcmp(args[0], "daemon")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200631 if (alertif_too_many_args(0, file, linenum, args, &err_code))
632 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200633 global.mode |= MODE_DAEMON;
634 }
635 else if (!strcmp(args[0], "debug")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200636 if (alertif_too_many_args(0, file, linenum, args, &err_code))
637 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200638 global.mode |= MODE_DEBUG;
639 }
640 else if (!strcmp(args[0], "noepoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200641 if (alertif_too_many_args(0, file, linenum, args, &err_code))
642 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100643 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200644 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200645 else if (!strcmp(args[0], "nokqueue")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200646 if (alertif_too_many_args(0, file, linenum, args, &err_code))
647 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100648 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200649 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200650 else if (!strcmp(args[0], "nopoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200651 if (alertif_too_many_args(0, file, linenum, args, &err_code))
652 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100653 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200654 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100655 else if (!strcmp(args[0], "nosplice")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200656 if (alertif_too_many_args(0, file, linenum, args, &err_code))
657 goto out;
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100658 global.tune.options &= ~GTUNE_USE_SPLICE;
659 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200660 else if (!strcmp(args[0], "nogetaddrinfo")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200661 if (alertif_too_many_args(0, file, linenum, args, &err_code))
662 goto out;
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200663 global.tune.options &= ~GTUNE_USE_GAI;
664 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200665 else if (!strcmp(args[0], "quiet")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200666 if (alertif_too_many_args(0, file, linenum, args, &err_code))
667 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200668 global.mode |= MODE_QUIET;
669 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200670 else if (!strcmp(args[0], "tune.maxpollevents")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200671 if (alertif_too_many_args(1, file, linenum, args, &err_code))
672 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200673 if (global.tune.maxpollevents != 0) {
674 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200675 err_code |= ERR_ALERT;
676 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200677 }
678 if (*(args[1]) == 0) {
679 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200680 err_code |= ERR_ALERT | ERR_FATAL;
681 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200682 }
683 global.tune.maxpollevents = atol(args[1]);
684 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100685 else if (!strcmp(args[0], "tune.maxaccept")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200686 if (alertif_too_many_args(1, file, linenum, args, &err_code))
687 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100688 if (global.tune.maxaccept != 0) {
689 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200690 err_code |= ERR_ALERT;
691 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100692 }
693 if (*(args[1]) == 0) {
694 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200695 err_code |= ERR_ALERT | ERR_FATAL;
696 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100697 }
698 global.tune.maxaccept = atol(args[1]);
699 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200700 else if (!strcmp(args[0], "tune.chksize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200701 if (alertif_too_many_args(1, file, linenum, args, &err_code))
702 goto out;
Willy Tarreau43961d52010-10-04 20:39:20 +0200703 if (*(args[1]) == 0) {
704 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
705 err_code |= ERR_ALERT | ERR_FATAL;
706 goto out;
707 }
708 global.tune.chksize = atol(args[1]);
709 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200710#ifdef USE_OPENSSL
Emeric Brun8dc60392014-05-09 13:52:00 +0200711 else if (!strcmp(args[0], "tune.ssl.force-private-cache")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200712 if (alertif_too_many_args(0, file, linenum, args, &err_code))
713 goto out;
Emeric Brun8dc60392014-05-09 13:52:00 +0200714 global.tune.sslprivatecache = 1;
715 }
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100716 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200717 if (alertif_too_many_args(1, file, linenum, args, &err_code))
718 goto out;
Emeric Brunfc32aca2012-09-03 12:10:29 +0200719 if (*(args[1]) == 0) {
720 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
721 err_code |= ERR_ALERT | ERR_FATAL;
722 goto out;
723 }
724 global.tune.sslcachesize = atol(args[1]);
725 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100726 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
727 unsigned int ssllifetime;
728 const char *res;
729
William Lallemand1a748ae2015-05-19 16:37:23 +0200730 if (alertif_too_many_args(1, file, linenum, args, &err_code))
731 goto out;
Emeric Brun4f65bff2012-11-16 15:11:00 +0100732 if (*(args[1]) == 0) {
733 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
734 err_code |= ERR_ALERT | ERR_FATAL;
735 goto out;
736 }
737
738 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
739 if (res) {
740 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
741 file, linenum, *res, args[0]);
742 err_code |= ERR_ALERT | ERR_FATAL;
743 goto out;
744 }
745
746 global.tune.ssllifetime = ssllifetime;
747 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100748 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200749 if (alertif_too_many_args(1, file, linenum, args, &err_code))
750 goto out;
Willy Tarreaubfd59462013-02-21 07:46:09 +0100751 if (*(args[1]) == 0) {
752 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
753 err_code |= ERR_ALERT | ERR_FATAL;
754 goto out;
755 }
756 global.tune.ssl_max_record = atol(args[1]);
757 }
Remi Gacogne47783ef2015-05-29 15:53:22 +0200758#ifndef OPENSSL_NO_DH
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200759 else if (!strcmp(args[0], "tune.ssl.default-dh-param")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200760 if (alertif_too_many_args(1, file, linenum, args, &err_code))
761 goto out;
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200762 if (*(args[1]) == 0) {
763 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
764 err_code |= ERR_ALERT | ERR_FATAL;
765 goto out;
766 }
767 global.tune.ssl_default_dh_param = atol(args[1]);
768 if (global.tune.ssl_default_dh_param < 1024) {
769 Alert("parsing [%s:%d] : '%s' expects a value >= 1024.\n", file, linenum, args[0]);
770 err_code |= ERR_ALERT | ERR_FATAL;
771 goto out;
772 }
773 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200774#endif
Christopher Faulet31af49d2015-06-09 17:29:50 +0200775 else if (!strcmp(args[0], "tune.ssl.ssl-ctx-cache-size")) {
776 if (alertif_too_many_args(1, file, linenum, args, &err_code))
777 goto out;
778 if (*(args[1]) == 0) {
779 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
780 err_code |= ERR_ALERT | ERR_FATAL;
781 goto out;
782 }
783 global.tune.ssl_ctx_cache = atoi(args[1]);
784 if (global.tune.ssl_ctx_cache < 0) {
785 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
786 file, linenum, args[0]);
787 err_code |= ERR_ALERT | ERR_FATAL;
788 goto out;
789 }
790 }
Remi Gacogne47783ef2015-05-29 15:53:22 +0200791#endif
Willy Tarreau33cb0652014-12-23 22:52:37 +0100792 else if (!strcmp(args[0], "tune.buffers.limit")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200793 if (alertif_too_many_args(1, file, linenum, args, &err_code))
794 goto out;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100795 if (*(args[1]) == 0) {
796 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
797 err_code |= ERR_ALERT | ERR_FATAL;
798 goto out;
799 }
800 global.tune.buf_limit = atol(args[1]);
801 if (global.tune.buf_limit) {
802 if (global.tune.buf_limit < 3)
803 global.tune.buf_limit = 3;
804 if (global.tune.buf_limit <= global.tune.reserved_bufs)
805 global.tune.buf_limit = global.tune.reserved_bufs + 1;
806 }
807 }
Willy Tarreau1058ae72014-12-23 22:40:40 +0100808 else if (!strcmp(args[0], "tune.buffers.reserve")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200809 if (alertif_too_many_args(1, file, linenum, args, &err_code))
810 goto out;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100811 if (*(args[1]) == 0) {
812 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
813 err_code |= ERR_ALERT | ERR_FATAL;
814 goto out;
815 }
816 global.tune.reserved_bufs = atol(args[1]);
817 if (global.tune.reserved_bufs < 2)
818 global.tune.reserved_bufs = 2;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100819 if (global.tune.buf_limit && global.tune.buf_limit <= global.tune.reserved_bufs)
820 global.tune.buf_limit = global.tune.reserved_bufs + 1;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100821 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200822 else if (!strcmp(args[0], "tune.bufsize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200823 if (alertif_too_many_args(1, file, linenum, args, &err_code))
824 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200825 if (*(args[1]) == 0) {
826 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
827 err_code |= ERR_ALERT | ERR_FATAL;
828 goto out;
829 }
830 global.tune.bufsize = atol(args[1]);
Willy Tarreau9b694542015-09-28 13:49:53 +0200831 if (global.tune.bufsize <= 0) {
832 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
833 err_code |= ERR_ALERT | ERR_FATAL;
834 goto out;
835 }
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100836 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100837 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200838 }
839 else if (!strcmp(args[0], "tune.maxrewrite")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200840 if (alertif_too_many_args(1, file, linenum, args, &err_code))
841 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200842 if (*(args[1]) == 0) {
843 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
844 err_code |= ERR_ALERT | ERR_FATAL;
845 goto out;
846 }
847 global.tune.maxrewrite = atol(args[1]);
Willy Tarreau27097842015-09-28 13:53:23 +0200848 if (global.tune.maxrewrite < 0) {
849 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
850 err_code |= ERR_ALERT | ERR_FATAL;
851 goto out;
852 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200853 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100854 else if (!strcmp(args[0], "tune.idletimer")) {
855 unsigned int idle;
856 const char *res;
857
William Lallemand1a748ae2015-05-19 16:37:23 +0200858 if (alertif_too_many_args(1, file, linenum, args, &err_code))
859 goto out;
Willy Tarreau7e312732014-02-12 16:35:14 +0100860 if (*(args[1]) == 0) {
861 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
862 err_code |= ERR_ALERT | ERR_FATAL;
863 goto out;
864 }
865
866 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
867 if (res) {
868 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
869 file, linenum, *res, args[0]);
870 err_code |= ERR_ALERT | ERR_FATAL;
871 goto out;
872 }
873
874 if (idle > 65535) {
875 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
876 err_code |= ERR_ALERT | ERR_FATAL;
877 goto out;
878 }
879 global.tune.idle_timer = idle;
880 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100881 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200882 if (alertif_too_many_args(1, file, linenum, args, &err_code))
883 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100884 if (global.tune.client_rcvbuf != 0) {
885 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
886 err_code |= ERR_ALERT;
887 goto out;
888 }
889 if (*(args[1]) == 0) {
890 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
891 err_code |= ERR_ALERT | ERR_FATAL;
892 goto out;
893 }
894 global.tune.client_rcvbuf = atol(args[1]);
895 }
896 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200897 if (alertif_too_many_args(1, file, linenum, args, &err_code))
898 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100899 if (global.tune.server_rcvbuf != 0) {
900 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
901 err_code |= ERR_ALERT;
902 goto out;
903 }
904 if (*(args[1]) == 0) {
905 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
906 err_code |= ERR_ALERT | ERR_FATAL;
907 goto out;
908 }
909 global.tune.server_rcvbuf = atol(args[1]);
910 }
911 else if (!strcmp(args[0], "tune.sndbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200912 if (alertif_too_many_args(1, file, linenum, args, &err_code))
913 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100914 if (global.tune.client_sndbuf != 0) {
915 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
916 err_code |= ERR_ALERT;
917 goto out;
918 }
919 if (*(args[1]) == 0) {
920 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
921 err_code |= ERR_ALERT | ERR_FATAL;
922 goto out;
923 }
924 global.tune.client_sndbuf = atol(args[1]);
925 }
926 else if (!strcmp(args[0], "tune.sndbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200927 if (alertif_too_many_args(1, file, linenum, args, &err_code))
928 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100929 if (global.tune.server_sndbuf != 0) {
930 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
931 err_code |= ERR_ALERT;
932 goto out;
933 }
934 if (*(args[1]) == 0) {
935 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
936 err_code |= ERR_ALERT | ERR_FATAL;
937 goto out;
938 }
939 global.tune.server_sndbuf = atol(args[1]);
940 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200941 else if (!strcmp(args[0], "tune.pipesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200942 if (alertif_too_many_args(1, file, linenum, args, &err_code))
943 goto out;
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200944 if (*(args[1]) == 0) {
945 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
946 err_code |= ERR_ALERT | ERR_FATAL;
947 goto out;
948 }
949 global.tune.pipesize = atol(args[1]);
950 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100951 else if (!strcmp(args[0], "tune.http.cookielen")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200952 if (alertif_too_many_args(1, file, linenum, args, &err_code))
953 goto out;
Willy Tarreau193b8c62012-11-22 00:17:38 +0100954 if (*(args[1]) == 0) {
955 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
956 err_code |= ERR_ALERT | ERR_FATAL;
957 goto out;
958 }
959 global.tune.cookie_len = atol(args[1]) + 1;
960 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200961 else if (!strcmp(args[0], "tune.http.maxhdr")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200962 if (alertif_too_many_args(1, file, linenum, args, &err_code))
963 goto out;
Willy Tarreauac1932d2011-10-24 19:14:41 +0200964 if (*(args[1]) == 0) {
965 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
966 err_code |= ERR_ALERT | ERR_FATAL;
967 goto out;
968 }
969 global.tune.max_http_hdr = atol(args[1]);
970 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100971 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
972#ifdef USE_ZLIB
William Lallemand1a748ae2015-05-19 16:37:23 +0200973 if (alertif_too_many_args(1, file, linenum, args, &err_code))
974 goto out;
William Lallemanda509e4c2012-11-07 16:54:34 +0100975 if (*args[1]) {
976 global.tune.zlibmemlevel = atoi(args[1]);
977 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
978 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
979 file, linenum, args[0]);
980 err_code |= ERR_ALERT | ERR_FATAL;
981 goto out;
982 }
983 } else {
984 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
985 file, linenum, args[0]);
986 err_code |= ERR_ALERT | ERR_FATAL;
987 goto out;
988 }
989#else
990 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
991 err_code |= ERR_ALERT | ERR_FATAL;
992 goto out;
993#endif
994 }
995 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
996#ifdef USE_ZLIB
William Lallemand1a748ae2015-05-19 16:37:23 +0200997 if (alertif_too_many_args(1, file, linenum, args, &err_code))
998 goto out;
William Lallemanda509e4c2012-11-07 16:54:34 +0100999 if (*args[1]) {
1000 global.tune.zlibwindowsize = atoi(args[1]);
1001 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
1002 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
1003 file, linenum, args[0]);
1004 err_code |= ERR_ALERT | ERR_FATAL;
1005 goto out;
1006 }
1007 } else {
1008 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
1009 file, linenum, args[0]);
1010 err_code |= ERR_ALERT | ERR_FATAL;
1011 goto out;
1012 }
1013#else
1014 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1015 err_code |= ERR_ALERT | ERR_FATAL;
1016 goto out;
1017#endif
1018 }
William Lallemandf3747832012-11-09 12:33:10 +01001019 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001020 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1021 goto out;
William Lallemandf3747832012-11-09 12:33:10 +01001022 if (*args[1]) {
1023 global.tune.comp_maxlevel = atoi(args[1]);
1024 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
1025 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1026 file, linenum, args[0]);
1027 err_code |= ERR_ALERT | ERR_FATAL;
1028 goto out;
1029 }
1030 } else {
1031 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1032 file, linenum, args[0]);
1033 err_code |= ERR_ALERT | ERR_FATAL;
1034 goto out;
1035 }
1036 }
Willy Tarreauf3045d22015-04-29 16:24:50 +02001037 else if (!strcmp(args[0], "tune.pattern.cache-size")) {
1038 if (*args[1]) {
1039 global.tune.pattern_cache = atoi(args[1]);
1040 if (global.tune.pattern_cache < 0) {
1041 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
1042 file, linenum, args[0]);
1043 err_code |= ERR_ALERT | ERR_FATAL;
1044 goto out;
1045 }
1046 } else {
1047 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
1048 file, linenum, args[0]);
1049 err_code |= ERR_ALERT | ERR_FATAL;
1050 goto out;
1051 }
1052 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001053 else if (!strcmp(args[0], "uid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001054 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1055 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001056 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001057 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001058 err_code |= ERR_ALERT;
1059 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001060 }
1061 if (*(args[1]) == 0) {
1062 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001063 err_code |= ERR_ALERT | ERR_FATAL;
1064 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001065 }
1066 global.uid = atol(args[1]);
1067 }
1068 else if (!strcmp(args[0], "gid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001069 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1070 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001071 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001072 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001073 err_code |= ERR_ALERT;
1074 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001075 }
1076 if (*(args[1]) == 0) {
1077 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001078 err_code |= ERR_ALERT | ERR_FATAL;
1079 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001080 }
1081 global.gid = atol(args[1]);
1082 }
Simon Horman98637e52014-06-20 12:30:16 +09001083 else if (!strcmp(args[0], "external-check")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001084 if (alertif_too_many_args(0, file, linenum, args, &err_code))
1085 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09001086 global.external_check = 1;
1087 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001088 /* user/group name handling */
1089 else if (!strcmp(args[0], "user")) {
1090 struct passwd *ha_user;
William Lallemand1a748ae2015-05-19 16:37:23 +02001091 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1092 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001093 if (global.uid != 0) {
1094 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001095 err_code |= ERR_ALERT;
1096 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001097 }
1098 errno = 0;
1099 ha_user = getpwnam(args[1]);
1100 if (ha_user != NULL) {
1101 global.uid = (int)ha_user->pw_uid;
1102 }
1103 else {
1104 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +02001105 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001106 }
1107 }
1108 else if (!strcmp(args[0], "group")) {
1109 struct group *ha_group;
William Lallemand1a748ae2015-05-19 16:37:23 +02001110 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1111 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001112 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02001113 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001114 err_code |= ERR_ALERT;
1115 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001116 }
1117 errno = 0;
1118 ha_group = getgrnam(args[1]);
1119 if (ha_group != NULL) {
1120 global.gid = (int)ha_group->gr_gid;
1121 }
1122 else {
1123 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +02001124 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001125 }
1126 }
1127 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +02001128 else if (!strcmp(args[0], "nbproc")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001129 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1130 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001131 if (*(args[1]) == 0) {
1132 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001133 err_code |= ERR_ALERT | ERR_FATAL;
1134 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001135 }
1136 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001137 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
1138 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
1139 file, linenum, args[0], LONGBITS, global.nbproc);
1140 err_code |= ERR_ALERT | ERR_FATAL;
1141 goto out;
1142 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001143 }
1144 else if (!strcmp(args[0], "maxconn")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001145 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1146 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001147 if (global.maxconn != 0) {
1148 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001149 err_code |= ERR_ALERT;
1150 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001151 }
1152 if (*(args[1]) == 0) {
1153 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001154 err_code |= ERR_ALERT | ERR_FATAL;
1155 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001156 }
1157 global.maxconn = atol(args[1]);
1158#ifdef SYSTEM_MAXCONN
1159 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
1160 Alert("parsing [%s:%d] : maxconn value %d too high for this system.\nLimiting to %d. Please use '-n' to force the value.\n", file, linenum, global.maxconn, DEFAULT_MAXCONN);
1161 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +02001162 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001163 }
1164#endif /* SYSTEM_MAXCONN */
1165 }
Willy Tarreau403edff2012-09-06 11:58:37 +02001166 else if (!strcmp(args[0], "maxsslconn")) {
1167#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001168 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1169 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001170 if (*(args[1]) == 0) {
1171 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1172 err_code |= ERR_ALERT | ERR_FATAL;
1173 goto out;
1174 }
1175 global.maxsslconn = atol(args[1]);
1176#else
Emeric Brun0914df82012-10-02 18:45:42 +02001177 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1178 err_code |= ERR_ALERT | ERR_FATAL;
1179 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001180#endif
1181 }
Willy Tarreau610f04b2014-02-13 11:36:41 +01001182 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
1183#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001184 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1185 goto out;
Willy Tarreau610f04b2014-02-13 11:36:41 +01001186 if (*(args[1]) == 0) {
1187 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1188 err_code |= ERR_ALERT | ERR_FATAL;
1189 goto out;
1190 }
1191 free(global.listen_default_ciphers);
1192 global.listen_default_ciphers = strdup(args[1]);
1193#else
1194 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1195 err_code |= ERR_ALERT | ERR_FATAL;
1196 goto out;
1197#endif
1198 }
1199 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
1200#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001201 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1202 goto out;
Willy Tarreau610f04b2014-02-13 11:36:41 +01001203 if (*(args[1]) == 0) {
1204 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1205 err_code |= ERR_ALERT | ERR_FATAL;
1206 goto out;
1207 }
1208 free(global.connect_default_ciphers);
1209 global.connect_default_ciphers = strdup(args[1]);
1210#else
1211 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1212 err_code |= ERR_ALERT | ERR_FATAL;
1213 goto out;
1214#endif
1215 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02001216#ifdef USE_OPENSSL
1217#ifndef OPENSSL_NO_DH
1218 else if (!strcmp(args[0], "ssl-dh-param-file")) {
1219 if (*(args[1]) == 0) {
1220 Alert("parsing [%s:%d] : '%s' expects a file path as an argument.\n", file, linenum, args[0]);
1221 err_code |= ERR_ALERT | ERR_FATAL;
1222 goto out;
1223 }
1224 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
1225 Alert("parsing [%s:%d] : '%s': unable to load DH parameters from file <%s>.\n", file, linenum, args[0], args[1]);
1226 err_code |= ERR_ALERT | ERR_FATAL;
1227 goto out;
1228 }
1229 }
1230#endif
1231#endif
Emeric Brun850efd52014-01-29 12:24:34 +01001232 else if (!strcmp(args[0], "ssl-server-verify")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001233 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1234 goto out;
Emeric Brun850efd52014-01-29 12:24:34 +01001235 if (*(args[1]) == 0) {
1236 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1237 err_code |= ERR_ALERT | ERR_FATAL;
1238 goto out;
1239 }
1240 if (strcmp(args[1],"none") == 0)
1241 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1242 else if (strcmp(args[1],"required") == 0)
1243 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1244 else {
1245 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1246 err_code |= ERR_ALERT | ERR_FATAL;
1247 goto out;
1248 }
1249 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001250 else if (!strcmp(args[0], "maxconnrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001251 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1252 goto out;
Willy Tarreau81c25d02011-09-07 15:17:21 +02001253 if (global.cps_lim != 0) {
1254 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1255 err_code |= ERR_ALERT;
1256 goto out;
1257 }
1258 if (*(args[1]) == 0) {
1259 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1260 err_code |= ERR_ALERT | ERR_FATAL;
1261 goto out;
1262 }
1263 global.cps_lim = atol(args[1]);
1264 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001265 else if (!strcmp(args[0], "maxsessrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001266 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1267 goto out;
Willy Tarreau93e7c002013-10-07 18:51:07 +02001268 if (global.sps_lim != 0) {
1269 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1270 err_code |= ERR_ALERT;
1271 goto out;
1272 }
1273 if (*(args[1]) == 0) {
1274 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1275 err_code |= ERR_ALERT | ERR_FATAL;
1276 goto out;
1277 }
1278 global.sps_lim = atol(args[1]);
1279 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001280 else if (!strcmp(args[0], "maxsslrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001281 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1282 goto out;
Willy Tarreaue43d5322013-10-07 20:01:52 +02001283 if (global.ssl_lim != 0) {
1284 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1285 err_code |= ERR_ALERT;
1286 goto out;
1287 }
1288 if (*(args[1]) == 0) {
1289 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1290 err_code |= ERR_ALERT | ERR_FATAL;
1291 goto out;
1292 }
1293 global.ssl_lim = atol(args[1]);
1294 }
William Lallemandd85f9172012-11-09 17:05:39 +01001295 else if (!strcmp(args[0], "maxcomprate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001296 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1297 goto out;
William Lallemandd85f9172012-11-09 17:05:39 +01001298 if (*(args[1]) == 0) {
1299 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1300 err_code |= ERR_ALERT | ERR_FATAL;
1301 goto out;
1302 }
1303 global.comp_rate_lim = atoi(args[1]) * 1024;
1304 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001305 else if (!strcmp(args[0], "maxpipes")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001306 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1307 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001308 if (global.maxpipes != 0) {
1309 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001310 err_code |= ERR_ALERT;
1311 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001312 }
1313 if (*(args[1]) == 0) {
1314 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001315 err_code |= ERR_ALERT | ERR_FATAL;
1316 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001317 }
1318 global.maxpipes = atol(args[1]);
1319 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001320 else if (!strcmp(args[0], "maxzlibmem")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001321 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1322 goto out;
William Lallemand9d5f5482012-11-07 16:12:57 +01001323 if (*(args[1]) == 0) {
1324 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1325 err_code |= ERR_ALERT | ERR_FATAL;
1326 goto out;
1327 }
William Lallemande3a7d992012-11-20 11:25:20 +01001328 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001329 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001330 else if (!strcmp(args[0], "maxcompcpuusage")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001331 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1332 goto out;
William Lallemand072a2bf2012-11-20 17:01:01 +01001333 if (*(args[1]) == 0) {
1334 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1335 err_code |= ERR_ALERT | ERR_FATAL;
1336 goto out;
1337 }
1338 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001339 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001340 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1341 err_code |= ERR_ALERT | ERR_FATAL;
1342 goto out;
1343 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001344 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001345
Willy Tarreaubaaee002006-06-26 02:48:02 +02001346 else if (!strcmp(args[0], "ulimit-n")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001347 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1348 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001349 if (global.rlimit_nofile != 0) {
1350 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001351 err_code |= ERR_ALERT;
1352 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001353 }
1354 if (*(args[1]) == 0) {
1355 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001356 err_code |= ERR_ALERT | ERR_FATAL;
1357 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001358 }
1359 global.rlimit_nofile = atol(args[1]);
1360 }
1361 else if (!strcmp(args[0], "chroot")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001362 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1363 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001364 if (global.chroot != NULL) {
1365 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001366 err_code |= ERR_ALERT;
1367 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001368 }
1369 if (*(args[1]) == 0) {
1370 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001371 err_code |= ERR_ALERT | ERR_FATAL;
1372 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001373 }
1374 global.chroot = strdup(args[1]);
1375 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001376 else if (!strcmp(args[0], "description")) {
1377 int i, len=0;
1378 char *d;
1379
1380 if (!*args[1]) {
1381 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1382 file, linenum, args[0]);
1383 err_code |= ERR_ALERT | ERR_FATAL;
1384 goto out;
1385 }
1386
Willy Tarreau348acfe2014-04-14 15:00:39 +02001387 for (i = 1; *args[i]; i++)
1388 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001389
1390 if (global.desc)
1391 free(global.desc);
1392
1393 global.desc = d = (char *)calloc(1, len);
1394
Willy Tarreau348acfe2014-04-14 15:00:39 +02001395 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1396 for (i = 2; *args[i]; i++)
1397 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001398 }
1399 else if (!strcmp(args[0], "node")) {
1400 int i;
1401 char c;
1402
William Lallemand1a748ae2015-05-19 16:37:23 +02001403 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1404 goto out;
1405
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001406 for (i=0; args[1][i]; i++) {
1407 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001408 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1409 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001410 break;
1411 }
1412
1413 if (!i || args[1][i]) {
1414 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1415 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1416 file, linenum, args[0]);
1417 err_code |= ERR_ALERT | ERR_FATAL;
1418 goto out;
1419 }
1420
1421 if (global.node)
1422 free(global.node);
1423
1424 global.node = strdup(args[1]);
1425 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001426 else if (!strcmp(args[0], "pidfile")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001427 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1428 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001429 if (global.pidfile != NULL) {
1430 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001431 err_code |= ERR_ALERT;
1432 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001433 }
1434 if (*(args[1]) == 0) {
1435 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001436 err_code |= ERR_ALERT | ERR_FATAL;
1437 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001438 }
1439 global.pidfile = strdup(args[1]);
1440 }
Emeric Bruned760922010-10-22 17:59:25 +02001441 else if (!strcmp(args[0], "unix-bind")) {
1442 int cur_arg = 1;
1443 while (*(args[cur_arg])) {
1444 if (!strcmp(args[cur_arg], "prefix")) {
1445 if (global.unix_bind.prefix != NULL) {
1446 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1447 err_code |= ERR_ALERT;
1448 cur_arg += 2;
1449 continue;
1450 }
1451
1452 if (*(args[cur_arg+1]) == 0) {
1453 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1454 err_code |= ERR_ALERT | ERR_FATAL;
1455 goto out;
1456 }
1457 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1458 cur_arg += 2;
1459 continue;
1460 }
1461
1462 if (!strcmp(args[cur_arg], "mode")) {
1463
1464 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1465 cur_arg += 2;
1466 continue;
1467 }
1468
1469 if (!strcmp(args[cur_arg], "uid")) {
1470
1471 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1472 cur_arg += 2;
1473 continue;
1474 }
1475
1476 if (!strcmp(args[cur_arg], "gid")) {
1477
1478 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1479 cur_arg += 2;
1480 continue;
1481 }
1482
1483 if (!strcmp(args[cur_arg], "user")) {
1484 struct passwd *user;
1485
1486 user = getpwnam(args[cur_arg + 1]);
1487 if (!user) {
1488 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1489 file, linenum, args[0], args[cur_arg + 1 ]);
1490 err_code |= ERR_ALERT | ERR_FATAL;
1491 goto out;
1492 }
1493
1494 global.unix_bind.ux.uid = user->pw_uid;
1495 cur_arg += 2;
1496 continue;
1497 }
1498
1499 if (!strcmp(args[cur_arg], "group")) {
1500 struct group *group;
1501
1502 group = getgrnam(args[cur_arg + 1]);
1503 if (!group) {
1504 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1505 file, linenum, args[0], args[cur_arg + 1 ]);
1506 err_code |= ERR_ALERT | ERR_FATAL;
1507 goto out;
1508 }
1509
1510 global.unix_bind.ux.gid = group->gr_gid;
1511 cur_arg += 2;
1512 continue;
1513 }
1514
Willy Tarreaub48f9582011-09-05 01:17:06 +02001515 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001516 file, linenum, args[0]);
1517 err_code |= ERR_ALERT | ERR_FATAL;
1518 goto out;
1519 }
1520 }
William Lallemand0f99e342011-10-12 17:50:54 +02001521 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1522 /* delete previous herited or defined syslog servers */
1523 struct logsrv *back;
1524 struct logsrv *tmp;
1525
1526 if (*(args[1]) != 0) {
1527 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1528 err_code |= ERR_ALERT | ERR_FATAL;
1529 goto out;
1530 }
1531
1532 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1533 LIST_DEL(&tmp->list);
1534 free(tmp);
1535 }
1536 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001537 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001538 struct sockaddr_storage *sk;
1539 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001540 struct logsrv *logsrv;
Willy Tarreau18324f52014-06-27 18:10:07 +02001541 int arg = 0;
1542 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001543
William Lallemand1a748ae2015-05-19 16:37:23 +02001544 if (alertif_too_many_args(8, file, linenum, args, &err_code)) /* does not strictly check optional arguments */
1545 goto out;
1546
Willy Tarreaubaaee002006-06-26 02:48:02 +02001547 if (*(args[1]) == 0 || *(args[2]) == 0) {
1548 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001549 err_code |= ERR_ALERT | ERR_FATAL;
1550 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001551 }
William Lallemand0f99e342011-10-12 17:50:54 +02001552
1553 logsrv = calloc(1, sizeof(struct logsrv));
1554
Willy Tarreau18324f52014-06-27 18:10:07 +02001555 /* just after the address, a length may be specified */
1556 if (strcmp(args[arg+2], "len") == 0) {
1557 len = atoi(args[arg+3]);
1558 if (len < 80 || len > 65535) {
1559 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1560 file, linenum, args[arg+3]);
1561 err_code |= ERR_ALERT | ERR_FATAL;
1562 goto out;
1563 }
1564 logsrv->maxlen = len;
1565
1566 /* skip these two args */
1567 arg += 2;
1568 }
1569 else
1570 logsrv->maxlen = MAX_SYSLOG_LEN;
1571
1572 if (logsrv->maxlen > global.max_syslog_len) {
1573 global.max_syslog_len = logsrv->maxlen;
Dragan Dosen59cee972015-09-19 22:09:02 +02001574 logheader = realloc(logheader, global.max_syslog_len + 1);
Dragan Dosen1322d092015-09-22 16:05:32 +02001575 logheader_rfc5424 = realloc(logheader_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02001576 logline = realloc(logline, global.max_syslog_len + 1);
Dragan Dosen0b85ece2015-09-25 19:17:44 +02001577 logline_rfc5424 = realloc(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02001578 }
1579
Dragan Dosen1322d092015-09-22 16:05:32 +02001580 /* after the length, a format may be specified */
1581 if (strcmp(args[arg+2], "format") == 0) {
1582 logsrv->format = get_log_format(args[arg+3]);
1583 if (logsrv->format < 0) {
1584 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
1585 err_code |= ERR_ALERT | ERR_FATAL;
1586 goto out;
1587 }
1588
1589 /* skip these two args */
1590 arg += 2;
1591 }
1592
William Lallemand1a748ae2015-05-19 16:37:23 +02001593 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
1594 goto out;
1595
Willy Tarreau18324f52014-06-27 18:10:07 +02001596 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001597 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001598 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001599 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001600 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001601 }
1602
William Lallemand0f99e342011-10-12 17:50:54 +02001603 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02001604 if (*(args[arg+3])) {
1605 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001606 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001607 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001608 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001609 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001610 }
1611 }
1612
William Lallemand0f99e342011-10-12 17:50:54 +02001613 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02001614 if (*(args[arg+4])) {
1615 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001616 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001617 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001618 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001619 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001620 }
1621 }
1622
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02001623 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001624 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001625 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001626 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001627 free(logsrv);
1628 goto out;
1629 }
1630 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001631
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001632 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001633 if (port1 != port2) {
1634 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1635 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001636 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001637 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001638 goto out;
1639 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001640
William Lallemand0f99e342011-10-12 17:50:54 +02001641 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001642 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001643 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001644 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001645
William Lallemand0f99e342011-10-12 17:50:54 +02001646 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001647 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001648 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1649 char *name;
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001650
1651 if (global.log_send_hostname != NULL) {
1652 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1653 err_code |= ERR_ALERT;
1654 goto out;
1655 }
1656
1657 if (*(args[1]))
1658 name = args[1];
1659 else
1660 name = hostname;
1661
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001662 free(global.log_send_hostname);
Dragan Dosenc8cfa7b2015-09-28 13:28:21 +02001663 global.log_send_hostname = strdup(name);
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001664 }
Baptiste Assmann6bc89362015-08-23 09:22:25 +02001665 else if (!strcmp(args[0], "server-state-base")) { /* path base where HAProxy can find server state files */
1666 if (global.server_state_base != NULL) {
1667 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1668 err_code |= ERR_ALERT;
1669 goto out;
1670 }
1671
1672 if (!*(args[1])) {
1673 Alert("parsing [%s:%d] : '%s' expects one argument: a directory path.\n", file, linenum, args[0]);
1674 err_code |= ERR_FATAL;
1675 goto out;
1676 }
1677
1678 global.server_state_base = strdup(args[1]);
1679 }
Baptiste Assmanne0882262015-08-23 09:54:31 +02001680 else if (!strcmp(args[0], "server-state-file")) { /* path to the file where HAProxy can load the server states */
1681 if (global.server_state_file != NULL) {
1682 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1683 err_code |= ERR_ALERT;
1684 goto out;
1685 }
1686
1687 if (!*(args[1])) {
1688 Alert("parsing [%s:%d] : '%s' expect one argument: a file path.\n", file, linenum, args[0]);
1689 err_code |= ERR_FATAL;
1690 goto out;
1691 }
1692
1693 global.server_state_file = strdup(args[1]);
1694 }
Kevinm48936af2010-12-22 16:08:21 +00001695 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
William Lallemand1a748ae2015-05-19 16:37:23 +02001696 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1697 goto out;
Kevinm48936af2010-12-22 16:08:21 +00001698 if (*(args[1]) == 0) {
1699 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1700 err_code |= ERR_ALERT | ERR_FATAL;
1701 goto out;
1702 }
Dragan Dosen43885c72015-10-01 13:18:13 +02001703 chunk_destroy(&global.log_tag);
1704 chunk_initstr(&global.log_tag, strdup(args[1]));
Kevinm48936af2010-12-22 16:08:21 +00001705 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001706 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
William Lallemand1a748ae2015-05-19 16:37:23 +02001707 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1708 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001709 if (global.spread_checks != 0) {
1710 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001711 err_code |= ERR_ALERT;
1712 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001713 }
1714 if (*(args[1]) == 0) {
1715 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001716 err_code |= ERR_ALERT | ERR_FATAL;
1717 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001718 }
1719 global.spread_checks = atol(args[1]);
1720 if (global.spread_checks < 0 || global.spread_checks > 50) {
1721 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001722 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001723 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001724 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001725 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1726 const char *err;
1727 unsigned int val;
1728
William Lallemand1a748ae2015-05-19 16:37:23 +02001729 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1730 goto out;
Willy Tarreau1746eec2014-04-25 10:46:47 +02001731 if (*(args[1]) == 0) {
1732 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1733 err_code |= ERR_ALERT | ERR_FATAL;
1734 goto out;
1735 }
1736
1737 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1738 if (err) {
1739 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1740 err_code |= ERR_ALERT | ERR_FATAL;
1741 }
1742 global.max_spread_checks = val;
1743 if (global.max_spread_checks < 0) {
1744 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1745 err_code |= ERR_ALERT | ERR_FATAL;
1746 }
1747 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001748 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1749#ifdef USE_CPU_AFFINITY
1750 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001751 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001752 unsigned long cpus = 0;
1753
1754 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001755 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001756 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001757 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001758 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001759 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001760 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001761 proc = atol(args[1]);
1762 if (proc >= 1 && proc <= LONGBITS)
1763 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001764 }
1765
1766 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001767 Alert("parsing [%s:%d]: %s expects a process number including 'all', 'odd', 'even', or a number from 1 to %d, followed by a list of CPU ranges with numbers from 0 to %d.\n",
1768 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001769 err_code |= ERR_ALERT | ERR_FATAL;
1770 goto out;
1771 }
1772
1773 cur_arg = 2;
1774 while (*args[cur_arg]) {
1775 unsigned int low, high;
1776
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001777 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001778 char *dash = strchr(args[cur_arg], '-');
1779
1780 low = high = str2uic(args[cur_arg]);
1781 if (dash)
1782 high = str2uic(dash + 1);
1783
1784 if (high < low) {
1785 unsigned int swap = low;
1786 low = high;
1787 high = swap;
1788 }
1789
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001790 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001791 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001792 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001793 err_code |= ERR_ALERT | ERR_FATAL;
1794 goto out;
1795 }
1796
1797 while (low <= high)
1798 cpus |= 1UL << low++;
1799 }
1800 else {
1801 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1802 file, linenum, args[0], args[cur_arg]);
1803 err_code |= ERR_ALERT | ERR_FATAL;
1804 goto out;
1805 }
1806 cur_arg++;
1807 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001808 for (i = 0; i < LONGBITS; i++)
1809 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001810 global.cpu_map[i] = cpus;
1811#else
1812 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1813 err_code |= ERR_ALERT | ERR_FATAL;
1814 goto out;
1815#endif
1816 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001817 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001818 struct cfg_kw_list *kwl;
1819 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001820 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001821
1822 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1823 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1824 if (kwl->kw[index].section != CFG_GLOBAL)
1825 continue;
1826 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001827 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001828 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001829 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001830 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001831 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001832 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001833 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001834 err_code |= ERR_WARN;
1835 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001836 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001837 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001838 }
1839 }
1840 }
1841
Willy Tarreaubaaee002006-06-26 02:48:02 +02001842 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001843 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001844 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001845
Willy Tarreau058e9072009-07-20 09:30:05 +02001846 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001847 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001848 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001849}
1850
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001851void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001852{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001853 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001854 defproxy.mode = PR_MODE_TCP;
1855 defproxy.state = PR_STNEW;
1856 defproxy.maxconn = cfg_maxpconn;
1857 defproxy.conn_retries = CONN_RETRIES;
Joseph Lynch726ab712015-05-11 23:25:34 -07001858 defproxy.redispatch_after = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001859
Simon Horman66183002013-02-23 10:16:43 +09001860 defproxy.defsrv.check.inter = DEF_CHKINTR;
1861 defproxy.defsrv.check.fastinter = 0;
1862 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001863 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1864 defproxy.defsrv.agent.fastinter = 0;
1865 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001866 defproxy.defsrv.check.rise = DEF_RISETIME;
1867 defproxy.defsrv.check.fall = DEF_FALLTIME;
1868 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1869 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001870 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001871 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001872 defproxy.defsrv.maxqueue = 0;
1873 defproxy.defsrv.minconn = 0;
1874 defproxy.defsrv.maxconn = 0;
1875 defproxy.defsrv.slowstart = 0;
1876 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1877 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1878 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Simon Horman64e34162015-02-06 11:11:57 +09001879
1880 defproxy.email_alert.level = LOG_ALERT;
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02001881 defproxy.load_server_state_from_file = PR_SRV_STATE_FILE_UNSPEC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001882}
1883
Willy Tarreauade5ec42010-01-28 19:33:49 +01001884
Willy Tarreau63af98d2014-05-18 08:11:41 +02001885/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1886 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1887 * ERR_FATAL in case of error.
1888 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001889static int create_cond_regex_rule(const char *file, int line,
1890 struct proxy *px, int dir, int action, int flags,
1891 const char *cmd, const char *reg, const char *repl,
1892 const char **cond_start)
1893{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001894 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001895 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001896 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001897 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001898 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001899 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001900 int cs;
1901 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001902
1903 if (px == &defproxy) {
1904 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001905 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001906 goto err;
1907 }
1908
1909 if (*reg == 0) {
1910 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001911 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001912 goto err;
1913 }
1914
1915 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001916 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001917
Willy Tarreau5321c422010-01-28 20:35:13 +01001918 if (cond_start &&
1919 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001920 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1921 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1922 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001923 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001924 goto err;
1925 }
1926 }
1927 else if (cond_start && **cond_start) {
1928 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1929 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001930 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001931 goto err;
1932 }
1933
Willy Tarreau63af98d2014-05-18 08:11:41 +02001934 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001935 (dir == SMP_OPT_DIR_REQ) ?
1936 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1937 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1938 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001939
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001940 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001941 if (!preg) {
1942 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001943 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001944 goto err;
1945 }
1946
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001947 cs = !(flags & REG_ICASE);
1948 cap = !(flags & REG_NOSUB);
1949 error = NULL;
1950 if (!regex_comp(reg, preg, cs, cap, &error)) {
1951 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1952 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001953 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001954 goto err;
1955 }
1956
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001957 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001958 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001959 if (repl && err) {
1960 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1961 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001962 ret_code |= ERR_ALERT | ERR_FATAL;
1963 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001964 }
1965
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001966 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001967 ret_code |= ERR_WARN;
1968
1969 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001970
Willy Tarreau63af98d2014-05-18 08:11:41 +02001971 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001972 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001973 err:
1974 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001975 free(errmsg);
1976 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001977}
1978
Willy Tarreaubaaee002006-06-26 02:48:02 +02001979/*
William Lallemand51097192015-04-14 16:35:22 +02001980 * Parse a line in a <listen>, <frontend> or <backend> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001981 * Returns the error code, 0 if OK, or any combination of :
1982 * - ERR_ABORT: must abort ASAP
1983 * - ERR_FATAL: we can continue parsing but not start the service
1984 * - ERR_WARN: a warning has been emitted
1985 * - ERR_ALERT: an alert has been emitted
1986 * Only the two first ones can stop processing, the two others are just
1987 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001988 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001989int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1990{
1991 static struct peers *curpeers = NULL;
1992 struct peer *newpeer = NULL;
1993 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001994 struct bind_conf *bind_conf;
1995 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001996 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001997 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001998
1999 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002000 if (!*args[1]) {
2001 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01002002 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002003 goto out;
2004 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002005
William Lallemand6e62fb62015-04-28 16:55:23 +02002006 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2007 goto out;
2008
Emeric Brun32da3c42010-09-23 18:39:19 +02002009 err = invalid_char(args[1]);
2010 if (err) {
2011 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2012 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01002013 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002014 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002015 }
2016
2017 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
2018 /*
2019 * If there are two proxies with the same name only following
2020 * combinations are allowed:
2021 */
2022 if (strcmp(curpeers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002023 Alert("Parsing [%s:%d]: peers section '%s' has the same name as another peers section declared at %s:%d.\n",
Emeric Brun32da3c42010-09-23 18:39:19 +02002024 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002025 err_code |= ERR_ALERT | ERR_FATAL;
Emeric Brun32da3c42010-09-23 18:39:19 +02002026 }
2027 }
2028
2029 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
2030 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2031 err_code |= ERR_ALERT | ERR_ABORT;
2032 goto out;
2033 }
2034
2035 curpeers->next = peers;
2036 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002037 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002038 curpeers->conf.line = linenum;
2039 curpeers->last_change = now.tv_sec;
2040 curpeers->id = strdup(args[1]);
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002041 curpeers->state = PR_STNEW;
Emeric Brun32da3c42010-09-23 18:39:19 +02002042 }
2043 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01002044 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01002045 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002046 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02002047
2048 if (!*args[2]) {
2049 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2050 file, linenum, args[0]);
2051 err_code |= ERR_ALERT | ERR_FATAL;
2052 goto out;
2053 }
2054
2055 err = invalid_char(args[1]);
2056 if (err) {
2057 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2058 file, linenum, *err, args[1]);
2059 err_code |= ERR_ALERT | ERR_FATAL;
2060 goto out;
2061 }
2062
2063 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
2064 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2065 err_code |= ERR_ALERT | ERR_ABORT;
2066 goto out;
2067 }
2068
2069 /* the peers are linked backwards first */
2070 curpeers->count++;
2071 newpeer->next = curpeers->remote;
2072 curpeers->remote = newpeer;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002073 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002074 newpeer->conf.line = linenum;
2075
2076 newpeer->last_change = now.tv_sec;
2077 newpeer->id = strdup(args[1]);
2078
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002079 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002080 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01002081 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002082 err_code |= ERR_ALERT | ERR_FATAL;
2083 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002084 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01002085
2086 proto = protocol_by_family(sk->ss_family);
2087 if (!proto || !proto->connect) {
2088 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2089 file, linenum, args[0], args[1]);
2090 err_code |= ERR_ALERT | ERR_FATAL;
2091 goto out;
2092 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002093
2094 if (port1 != port2) {
2095 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2096 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002097 err_code |= ERR_ALERT | ERR_FATAL;
2098 goto out;
2099 }
2100
Willy Tarreau2aa38802013-02-20 19:20:59 +01002101 if (!port1) {
2102 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2103 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002104 err_code |= ERR_ALERT | ERR_FATAL;
2105 goto out;
2106 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002107
Emeric Brun32da3c42010-09-23 18:39:19 +02002108 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002109 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002110 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02002111 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02002112
Emeric Brun32da3c42010-09-23 18:39:19 +02002113 if (strcmp(newpeer->id, localpeer) == 0) {
2114 /* Current is local peer, it define a frontend */
2115 newpeer->local = 1;
Emeric Brunb3971ab2015-05-12 18:49:09 +02002116 peers->local = newpeer;
Emeric Brun32da3c42010-09-23 18:39:19 +02002117
2118 if (!curpeers->peers_fe) {
2119 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
2120 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2121 err_code |= ERR_ALERT | ERR_ABORT;
2122 goto out;
2123 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002124
Willy Tarreau237250c2011-07-29 01:49:03 +02002125 init_new_proxy(curpeers->peers_fe);
2126 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02002127 curpeers->peers_fe->id = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002128 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
2129 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau91d96282015-03-13 15:47:26 +01002130 peers_setup_frontend(curpeers->peers_fe);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002131
2132 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
2133
Willy Tarreau902636f2013-03-10 19:44:48 +01002134 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
2135 if (errmsg && *errmsg) {
2136 indent_msg(&errmsg, 2);
2137 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002138 }
2139 else
2140 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
2141 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002142 err_code |= ERR_FATAL;
2143 goto out;
2144 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02002145
2146 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01002147 l->maxaccept = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002148 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
2149 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
Willy Tarreau9903f0e2015-04-04 18:50:31 +02002150 l->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02002151 l->handler = process_stream;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002152 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01002153 l->default_target = ((struct proxy *)curpeers->peers_fe)->default_target;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002154 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
2155 global.maxsock += l->maxconn;
2156 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002157 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01002158 else {
2159 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
2160 file, linenum, args[0], args[1],
2161 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
2162 err_code |= ERR_FATAL;
2163 goto out;
2164 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002165 }
2166 } /* neither "peer" nor "peers" */
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002167 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
2168 curpeers->state = PR_STSTOPPED;
2169 }
2170 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
2171 curpeers->state = PR_STNEW;
2172 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002173 else if (*args[0] != 0) {
2174 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2175 err_code |= ERR_ALERT | ERR_FATAL;
2176 goto out;
2177 }
2178
2179out:
Willy Tarreau902636f2013-03-10 19:44:48 +01002180 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02002181 return err_code;
2182}
2183
Baptiste Assmann325137d2015-04-13 23:40:55 +02002184/*
2185 * Parse a <resolvers> section.
2186 * Returns the error code, 0 if OK, or any combination of :
2187 * - ERR_ABORT: must abort ASAP
2188 * - ERR_FATAL: we can continue parsing but not start the service
2189 * - ERR_WARN: a warning has been emitted
2190 * - ERR_ALERT: an alert has been emitted
2191 * Only the two first ones can stop processing, the two others are just
2192 * indicators.
2193 */
2194int cfg_parse_resolvers(const char *file, int linenum, char **args, int kwm)
2195{
2196 static struct dns_resolvers *curr_resolvers = NULL;
2197 struct dns_nameserver *newnameserver = NULL;
2198 const char *err;
2199 int err_code = 0;
2200 char *errmsg = NULL;
2201
2202 if (strcmp(args[0], "resolvers") == 0) { /* new resolvers section */
2203 if (!*args[1]) {
2204 Alert("parsing [%s:%d] : missing name for resolvers section.\n", file, linenum);
2205 err_code |= ERR_ALERT | ERR_ABORT;
2206 goto out;
2207 }
2208
2209 err = invalid_char(args[1]);
2210 if (err) {
2211 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2212 file, linenum, *err, args[0], args[1]);
2213 err_code |= ERR_ALERT | ERR_ABORT;
2214 goto out;
2215 }
2216
2217 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
2218 /* Error if two resolvers owns the same name */
2219 if (strcmp(curr_resolvers->id, args[1]) == 0) {
2220 Alert("Parsing [%s:%d]: resolvers '%s' has same name as another resolvers (declared at %s:%d).\n",
2221 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2222 err_code |= ERR_ALERT | ERR_ABORT;
2223 }
2224 }
2225
2226 if ((curr_resolvers = (struct dns_resolvers *)calloc(1, sizeof(struct dns_resolvers))) == NULL) {
2227 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2228 err_code |= ERR_ALERT | ERR_ABORT;
2229 goto out;
2230 }
2231
2232 /* default values */
2233 LIST_ADDQ(&dns_resolvers, &curr_resolvers->list);
2234 curr_resolvers->conf.file = strdup(file);
2235 curr_resolvers->conf.line = linenum;
2236 curr_resolvers->id = strdup(args[1]);
2237 curr_resolvers->query_ids = EB_ROOT;
2238 /* default hold period for valid is 10s */
Baptiste Assmann4c5490a2015-07-14 21:42:49 +02002239 curr_resolvers->hold.valid = 10000;
2240 curr_resolvers->timeout.retry = 1000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002241 curr_resolvers->resolve_retries = 3;
2242 LIST_INIT(&curr_resolvers->nameserver_list);
2243 LIST_INIT(&curr_resolvers->curr_resolution);
2244 }
2245 else if (strcmp(args[0], "nameserver") == 0) { /* nameserver definition */
2246 struct sockaddr_storage *sk;
2247 int port1, port2;
2248 struct protocol *proto;
2249
2250 if (!*args[2]) {
2251 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2252 file, linenum, args[0]);
2253 err_code |= ERR_ALERT | ERR_FATAL;
2254 goto out;
2255 }
2256
2257 err = invalid_char(args[1]);
2258 if (err) {
2259 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2260 file, linenum, *err, args[1]);
2261 err_code |= ERR_ALERT | ERR_FATAL;
2262 goto out;
2263 }
2264
2265 if ((newnameserver = (struct dns_nameserver *)calloc(1, sizeof(struct dns_nameserver))) == NULL) {
2266 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2267 err_code |= ERR_ALERT | ERR_ABORT;
2268 goto out;
2269 }
2270
2271 /* the nameservers are linked backward first */
2272 LIST_ADDQ(&curr_resolvers->nameserver_list, &newnameserver->list);
2273 curr_resolvers->count_nameservers++;
2274 newnameserver->resolvers = curr_resolvers;
2275 newnameserver->conf.file = strdup(file);
2276 newnameserver->conf.line = linenum;
2277 newnameserver->id = strdup(args[1]);
2278
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002279 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002280 if (!sk) {
2281 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2282 err_code |= ERR_ALERT | ERR_FATAL;
2283 goto out;
2284 }
2285
2286 proto = protocol_by_family(sk->ss_family);
2287 if (!proto || !proto->connect) {
2288 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2289 file, linenum, args[0], args[1]);
2290 err_code |= ERR_ALERT | ERR_FATAL;
2291 goto out;
2292 }
2293
2294 if (port1 != port2) {
2295 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2296 file, linenum, args[0], args[1], args[2]);
2297 err_code |= ERR_ALERT | ERR_FATAL;
2298 goto out;
2299 }
2300
2301 newnameserver->addr = *sk;
2302 }
2303 else if (strcmp(args[0], "hold") == 0) { /* hold periods */
2304 const char *res;
2305 unsigned int time;
2306
2307 if (!*args[2]) {
2308 Alert("parsing [%s:%d] : '%s' expects an <event> and a <time> as arguments.\n",
2309 file, linenum, args[0]);
2310 Alert("<event> can be either 'valid', 'nx', 'refused', 'timeout', or 'other'\n");
2311 err_code |= ERR_ALERT | ERR_FATAL;
2312 goto out;
2313 }
2314 res = parse_time_err(args[2], &time, TIME_UNIT_MS);
2315 if (res) {
2316 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2317 file, linenum, *res, args[0]);
2318 err_code |= ERR_ALERT | ERR_FATAL;
2319 goto out;
2320 }
2321 if (strcmp(args[1], "valid") == 0)
2322 curr_resolvers->hold.valid = time;
2323 else {
2324 Alert("parsing [%s:%d] : '%s' unknown <event>: '%s', expects 'valid'\n",
2325 file, linenum, args[0], args[1]);
2326 err_code |= ERR_ALERT | ERR_FATAL;
2327 goto out;
2328 }
2329
2330 }
2331 else if (strcmp(args[0], "resolve_retries") == 0) {
2332 if (!*args[1]) {
2333 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2334 file, linenum, args[0]);
2335 err_code |= ERR_ALERT | ERR_FATAL;
2336 goto out;
2337 }
2338 curr_resolvers->resolve_retries = atoi(args[1]);
2339 }
2340 else if (strcmp(args[0], "timeout") == 0) {
2341 const char *res;
2342 unsigned int timeout_retry;
2343
2344 if (!*args[2]) {
2345 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments.\n",
2346 file, linenum, args[0]);
2347 err_code |= ERR_ALERT | ERR_FATAL;
2348 goto out;
2349 }
2350 res = parse_time_err(args[2], &timeout_retry, TIME_UNIT_MS);
2351 if (res) {
2352 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2353 file, linenum, *res, args[0]);
2354 err_code |= ERR_ALERT | ERR_FATAL;
2355 goto out;
2356 }
2357 curr_resolvers->timeout.retry = timeout_retry;
2358 } /* neither "nameserver" nor "resolvers" */
2359 else if (*args[0] != 0) {
2360 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2361 err_code |= ERR_ALERT | ERR_FATAL;
2362 goto out;
2363 }
2364
2365 out:
2366 free(errmsg);
2367 return err_code;
2368}
Simon Horman0d16a402015-01-30 11:22:58 +09002369
2370/*
William Lallemand51097192015-04-14 16:35:22 +02002371 * Parse a line in a <listen>, <frontend> or <backend> section.
Simon Horman0d16a402015-01-30 11:22:58 +09002372 * Returns the error code, 0 if OK, or any combination of :
2373 * - ERR_ABORT: must abort ASAP
2374 * - ERR_FATAL: we can continue parsing but not start the service
2375 * - ERR_WARN: a warning has been emitted
2376 * - ERR_ALERT: an alert has been emitted
2377 * Only the two first ones can stop processing, the two others are just
2378 * indicators.
2379 */
2380int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
2381{
2382 static struct mailers *curmailers = NULL;
2383 struct mailer *newmailer = NULL;
2384 const char *err;
2385 int err_code = 0;
2386 char *errmsg = NULL;
2387
2388 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
2389 if (!*args[1]) {
2390 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
2391 err_code |= ERR_ALERT | ERR_ABORT;
2392 goto out;
2393 }
2394
2395 err = invalid_char(args[1]);
2396 if (err) {
2397 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2398 file, linenum, *err, args[0], args[1]);
2399 err_code |= ERR_ALERT | ERR_ABORT;
2400 goto out;
2401 }
2402
2403 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
2404 /*
2405 * If there are two proxies with the same name only following
2406 * combinations are allowed:
2407 */
2408 if (strcmp(curmailers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002409 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 +09002410 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002411 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman0d16a402015-01-30 11:22:58 +09002412 }
2413 }
2414
2415 if ((curmailers = (struct mailers *)calloc(1, sizeof(struct mailers))) == NULL) {
2416 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2417 err_code |= ERR_ALERT | ERR_ABORT;
2418 goto out;
2419 }
2420
2421 curmailers->next = mailers;
2422 mailers = curmailers;
2423 curmailers->conf.file = strdup(file);
2424 curmailers->conf.line = linenum;
2425 curmailers->id = strdup(args[1]);
2426 }
2427 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
2428 struct sockaddr_storage *sk;
2429 int port1, port2;
2430 struct protocol *proto;
2431
2432 if (!*args[2]) {
2433 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2434 file, linenum, args[0]);
2435 err_code |= ERR_ALERT | ERR_FATAL;
2436 goto out;
2437 }
2438
2439 err = invalid_char(args[1]);
2440 if (err) {
2441 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2442 file, linenum, *err, args[1]);
2443 err_code |= ERR_ALERT | ERR_FATAL;
2444 goto out;
2445 }
2446
2447 if ((newmailer = (struct mailer *)calloc(1, sizeof(struct mailer))) == NULL) {
2448 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2449 err_code |= ERR_ALERT | ERR_ABORT;
2450 goto out;
2451 }
2452
2453 /* the mailers are linked backwards first */
2454 curmailers->count++;
2455 newmailer->next = curmailers->mailer_list;
2456 curmailers->mailer_list = newmailer;
2457 newmailer->mailers = curmailers;
2458 newmailer->conf.file = strdup(file);
2459 newmailer->conf.line = linenum;
2460
2461 newmailer->id = strdup(args[1]);
2462
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002463 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Simon Horman0d16a402015-01-30 11:22:58 +09002464 if (!sk) {
2465 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2466 err_code |= ERR_ALERT | ERR_FATAL;
2467 goto out;
2468 }
2469
2470 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002471 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2472 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002473 file, linenum, args[0], args[1]);
2474 err_code |= ERR_ALERT | ERR_FATAL;
2475 goto out;
2476 }
2477
2478 if (port1 != port2) {
2479 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2480 file, linenum, args[0], args[1], args[2]);
2481 err_code |= ERR_ALERT | ERR_FATAL;
2482 goto out;
2483 }
2484
2485 if (!port1) {
2486 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2487 file, linenum, args[0], args[1], args[2]);
2488 err_code |= ERR_ALERT | ERR_FATAL;
2489 goto out;
2490 }
2491
2492 newmailer->addr = *sk;
2493 newmailer->proto = proto;
2494 newmailer->xprt = &raw_sock;
2495 newmailer->sock_init_arg = NULL;
2496 } /* neither "mailer" nor "mailers" */
2497 else if (*args[0] != 0) {
2498 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2499 err_code |= ERR_ALERT | ERR_FATAL;
2500 goto out;
2501 }
2502
2503out:
2504 free(errmsg);
2505 return err_code;
2506}
2507
Simon Horman9dc49962015-01-30 11:22:59 +09002508static void free_email_alert(struct proxy *p)
2509{
2510 free(p->email_alert.mailers.name);
2511 p->email_alert.mailers.name = NULL;
2512 free(p->email_alert.from);
2513 p->email_alert.from = NULL;
2514 free(p->email_alert.to);
2515 p->email_alert.to = NULL;
2516 free(p->email_alert.myhostname);
2517 p->email_alert.myhostname = NULL;
2518}
2519
Willy Tarreau3842f002009-06-14 11:39:52 +02002520int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002521{
2522 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002523 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002524 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002525 int rc;
2526 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002527 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002528 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002529 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002530 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002531 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002532
Willy Tarreau977b8e42006-12-29 14:19:17 +01002533 if (!strcmp(args[0], "listen"))
2534 rc = PR_CAP_LISTEN;
2535 else if (!strcmp(args[0], "frontend"))
2536 rc = PR_CAP_FE | PR_CAP_RS;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02002537 else if (!strcmp(args[0], "backend"))
Willy Tarreau977b8e42006-12-29 14:19:17 +01002538 rc = PR_CAP_BE | PR_CAP_RS;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002539 else
2540 rc = PR_CAP_NONE;
2541
2542 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002543 if (!*args[1]) {
2544 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
2545 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
2546 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002547 err_code |= ERR_ALERT | ERR_ABORT;
2548 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002549 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002550
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002551 err = invalid_char(args[1]);
2552 if (err) {
2553 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2554 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002555 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002556 }
2557
Willy Tarreau8f50b682015-05-26 11:45:02 +02002558 curproxy = (rc & PR_CAP_FE) ? proxy_fe_by_name(args[1]) : proxy_be_by_name(args[1]);
2559 if (curproxy) {
2560 Alert("Parsing [%s:%d]: %s '%s' has the same name as %s '%s' declared at %s:%d.\n",
2561 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2562 curproxy->id, curproxy->conf.file, curproxy->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002563 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002564 }
2565
Willy Tarreaubaaee002006-06-26 02:48:02 +02002566 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
2567 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002568 err_code |= ERR_ALERT | ERR_ABORT;
2569 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002570 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002571
Willy Tarreau97cb7802010-01-03 20:23:58 +01002572 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002573 curproxy->next = proxy;
2574 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002575 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2576 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002577 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002578 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002579 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002580 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002581
William Lallemand6e62fb62015-04-28 16:55:23 +02002582 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2583 if (curproxy->cap & PR_CAP_FE)
2584 Alert("parsing [%s:%d] : please use the 'bind' keyword for listening addresses.\n", file, linenum);
2585 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002586 }
2587
2588 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002589 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002590 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002591
Willy Tarreaubaaee002006-06-26 02:48:02 +02002592 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002593 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002594 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002595 curproxy->no_options = defproxy.no_options;
2596 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002597 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002598 curproxy->except_net = defproxy.except_net;
2599 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002600 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002601 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002602
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002603 if (defproxy.fwdfor_hdr_len) {
2604 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2605 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2606 }
2607
Willy Tarreaub86db342009-11-30 11:50:16 +01002608 if (defproxy.orgto_hdr_len) {
2609 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2610 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2611 }
2612
Mark Lamourinec2247f02012-01-04 13:02:01 -05002613 if (defproxy.server_id_hdr_len) {
2614 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2615 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2616 }
2617
Willy Tarreau977b8e42006-12-29 14:19:17 +01002618 if (curproxy->cap & PR_CAP_FE) {
2619 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002620 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002621 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002622
2623 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002624 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2625 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002626
2627 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2628 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002629
Willy Tarreau977b8e42006-12-29 14:19:17 +01002630 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002631 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002632 curproxy->fullconn = defproxy.fullconn;
2633 curproxy->conn_retries = defproxy.conn_retries;
Joseph Lynch726ab712015-05-11 23:25:34 -07002634 curproxy->redispatch_after = defproxy.redispatch_after;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002635 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002636
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002637 if (defproxy.check_req) {
2638 curproxy->check_req = calloc(1, defproxy.check_len);
2639 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2640 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002641 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002642
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002643 if (defproxy.expect_str) {
2644 curproxy->expect_str = strdup(defproxy.expect_str);
2645 if (defproxy.expect_regex) {
2646 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002647 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2648 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002649 }
2650 }
2651
Willy Tarreau67402132012-05-31 20:40:20 +02002652 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002653 if (defproxy.cookie_name)
2654 curproxy->cookie_name = strdup(defproxy.cookie_name);
2655 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002656 if (defproxy.cookie_domain)
2657 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002658
Willy Tarreau31936852010-10-06 16:59:56 +02002659 if (defproxy.cookie_maxidle)
2660 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2661
2662 if (defproxy.cookie_maxlife)
2663 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2664
Emeric Brun647caf12009-06-30 17:57:00 +02002665 if (defproxy.rdp_cookie_name)
2666 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2667 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2668
Willy Tarreau01732802007-11-01 22:48:15 +01002669 if (defproxy.url_param_name)
2670 curproxy->url_param_name = strdup(defproxy.url_param_name);
2671 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002672
Benoitaffb4812009-03-25 13:02:10 +01002673 if (defproxy.hh_name)
2674 curproxy->hh_name = strdup(defproxy.hh_name);
2675 curproxy->hh_len = defproxy.hh_len;
2676 curproxy->hh_match_domain = defproxy.hh_match_domain;
2677
Willy Tarreauef9a3602012-12-08 22:29:20 +01002678 if (defproxy.conn_src.iface_name)
2679 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2680 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002681 curproxy->conn_src.opts = defproxy.conn_src.opts;
Willy Tarreau29fbe512015-08-20 19:35:14 +02002682#if defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002683 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002684#endif
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02002685 curproxy->load_server_state_from_file = defproxy.load_server_state_from_file;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002686 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002687
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002688 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002689 if (defproxy.capture_name)
2690 curproxy->capture_name = strdup(defproxy.capture_name);
2691 curproxy->capture_namelen = defproxy.capture_namelen;
2692 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002693 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002694
Willy Tarreau977b8e42006-12-29 14:19:17 +01002695 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002696 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002697 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002698 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002699 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002700 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002701 curproxy->mon_net = defproxy.mon_net;
2702 curproxy->mon_mask = defproxy.mon_mask;
2703 if (defproxy.monitor_uri)
2704 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2705 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002706 if (defproxy.defbe.name)
2707 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002708
2709 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002710 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2711 if (curproxy->conf.logformat_string &&
2712 curproxy->conf.logformat_string != default_http_log_format &&
2713 curproxy->conf.logformat_string != default_tcp_log_format &&
2714 curproxy->conf.logformat_string != clf_http_log_format)
2715 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2716
2717 if (defproxy.conf.lfs_file) {
2718 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2719 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2720 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002721
2722 /* get either a pointer to the logformat string for RFC5424 structured-data or a copy of it */
2723 curproxy->conf.logformat_sd_string = defproxy.conf.logformat_sd_string;
2724 if (curproxy->conf.logformat_sd_string &&
2725 curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
2726 curproxy->conf.logformat_sd_string = strdup(curproxy->conf.logformat_sd_string);
2727
2728 if (defproxy.conf.lfsd_file) {
2729 curproxy->conf.lfsd_file = strdup(defproxy.conf.lfsd_file);
2730 curproxy->conf.lfsd_line = defproxy.conf.lfsd_line;
2731 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002732 }
2733
2734 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002735 curproxy->timeout.connect = defproxy.timeout.connect;
2736 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002737 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002738 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002739 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002740 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002741 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002742 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002743 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002744 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002745 }
2746
Willy Tarreaubaaee002006-06-26 02:48:02 +02002747 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002748 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002749
2750 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002751 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002752 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002753 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002754 LIST_INIT(&node->list);
2755 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2756 }
2757
Willy Tarreau62a61232013-04-12 18:13:46 +02002758 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2759 if (curproxy->conf.uniqueid_format_string)
2760 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2761
Dragan Dosen43885c72015-10-01 13:18:13 +02002762 chunk_dup(&curproxy->log_tag, &defproxy.log_tag);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002763
Willy Tarreau62a61232013-04-12 18:13:46 +02002764 if (defproxy.conf.uif_file) {
2765 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2766 curproxy->conf.uif_line = defproxy.conf.uif_line;
2767 }
William Lallemanda73203e2012-03-12 12:48:57 +01002768
2769 /* copy default header unique id */
2770 if (defproxy.header_unique_id)
2771 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2772
William Lallemand82fe75c2012-10-23 10:25:10 +02002773 /* default compression options */
2774 if (defproxy.comp != NULL) {
2775 curproxy->comp = calloc(1, sizeof(struct comp));
2776 curproxy->comp->algos = defproxy.comp->algos;
2777 curproxy->comp->types = defproxy.comp->types;
2778 }
2779
Willy Tarreaubaaee002006-06-26 02:48:02 +02002780 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002781 curproxy->conf.used_listener_id = EB_ROOT;
2782 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002783
Simon Horman98637e52014-06-20 12:30:16 +09002784 if (defproxy.check_path)
2785 curproxy->check_path = strdup(defproxy.check_path);
2786 if (defproxy.check_command)
2787 curproxy->check_command = strdup(defproxy.check_command);
2788
Simon Horman9dc49962015-01-30 11:22:59 +09002789 if (defproxy.email_alert.mailers.name)
2790 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2791 if (defproxy.email_alert.from)
2792 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2793 if (defproxy.email_alert.to)
2794 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2795 if (defproxy.email_alert.myhostname)
2796 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09002797 curproxy->email_alert.level = defproxy.email_alert.level;
Simon Horman9dc49962015-01-30 11:22:59 +09002798
Willy Tarreau93893792009-07-23 13:19:11 +02002799 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002800 }
2801 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2802 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002803 /* FIXME-20070101: we should do this too at the end of the
2804 * config parsing to free all default values.
2805 */
William Lallemand6e62fb62015-04-28 16:55:23 +02002806 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2807 err_code |= ERR_ABORT;
2808 goto out;
2809 }
2810
Willy Tarreaua534fea2008-08-03 12:19:50 +02002811 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002812 free(defproxy.check_command);
2813 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002814 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002815 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002816 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002817 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002818 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002819 free(defproxy.capture_name);
2820 free(defproxy.monitor_uri);
2821 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002822 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002823 free(defproxy.fwdfor_hdr_name);
2824 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002825 free(defproxy.orgto_hdr_name);
2826 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002827 free(defproxy.server_id_hdr_name);
2828 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002829 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002830 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002831 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002832 free(defproxy.expect_regex);
2833 defproxy.expect_regex = NULL;
2834 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002835
Willy Tarreau62a61232013-04-12 18:13:46 +02002836 if (defproxy.conf.logformat_string != default_http_log_format &&
2837 defproxy.conf.logformat_string != default_tcp_log_format &&
2838 defproxy.conf.logformat_string != clf_http_log_format)
2839 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002840
Willy Tarreau62a61232013-04-12 18:13:46 +02002841 free(defproxy.conf.uniqueid_format_string);
2842 free(defproxy.conf.lfs_file);
2843 free(defproxy.conf.uif_file);
Dragan Dosen43885c72015-10-01 13:18:13 +02002844 chunk_destroy(&defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09002845 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02002846
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002847 if (defproxy.conf.logformat_sd_string != default_rfc5424_sd_log_format)
2848 free(defproxy.conf.logformat_sd_string);
2849 free(defproxy.conf.lfsd_file);
2850
Willy Tarreaua534fea2008-08-03 12:19:50 +02002851 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002852 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002853
Willy Tarreaubaaee002006-06-26 02:48:02 +02002854 /* we cannot free uri_auth because it might already be used */
2855 init_default_instance();
2856 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002857 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2858 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002859 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002860 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002861 }
2862 else if (curproxy == NULL) {
2863 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002864 err_code |= ERR_ALERT | ERR_FATAL;
2865 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002866 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002867
2868 /* update the current file and line being parsed */
2869 curproxy->conf.args.file = curproxy->conf.file;
2870 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002871
2872 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002873 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2874 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2875 if (err_code & ERR_FATAL)
2876 goto out;
2877 }
2878 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002879 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002880 int cur_arg;
2881
Willy Tarreaubaaee002006-06-26 02:48:02 +02002882 if (curproxy == &defproxy) {
2883 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002884 err_code |= ERR_ALERT | ERR_FATAL;
2885 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002886 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002887 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002888 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002889
Willy Tarreau24709282013-03-10 21:32:12 +01002890 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002891 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002892 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002893 err_code |= ERR_ALERT | ERR_FATAL;
2894 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002895 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002896
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002897 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002898
2899 /* use default settings for unix sockets */
2900 bind_conf->ux.uid = global.unix_bind.ux.uid;
2901 bind_conf->ux.gid = global.unix_bind.ux.gid;
2902 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002903
2904 /* NOTE: the following line might create several listeners if there
2905 * are comma-separated IPs or port ranges. So all further processing
2906 * will have to be applied to all listeners created after last_listen.
2907 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002908 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2909 if (errmsg && *errmsg) {
2910 indent_msg(&errmsg, 2);
2911 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002912 }
2913 else
2914 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2915 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002916 err_code |= ERR_ALERT | ERR_FATAL;
2917 goto out;
2918 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002919
Willy Tarreau4348fad2012-09-20 16:48:07 +02002920 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2921 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002922 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002923 }
2924
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002925 cur_arg = 2;
2926 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002927 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002928 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002929 char *err;
2930
Willy Tarreau26982662012-09-12 23:17:10 +02002931 kw = bind_find_kw(args[cur_arg]);
2932 if (kw) {
2933 char *err = NULL;
2934 int code;
2935
2936 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002937 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2938 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002939 cur_arg += 1 + kw->skip ;
2940 err_code |= ERR_ALERT | ERR_FATAL;
2941 goto out;
2942 }
2943
Willy Tarreau4348fad2012-09-20 16:48:07 +02002944 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002945 err_code |= code;
2946
2947 if (code) {
2948 if (err && *err) {
2949 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002950 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002951 }
2952 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002953 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2954 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002955 if (code & ERR_FATAL) {
2956 free(err);
2957 cur_arg += 1 + kw->skip;
2958 goto out;
2959 }
2960 }
2961 free(err);
2962 cur_arg += 1 + kw->skip;
2963 continue;
2964 }
2965
Willy Tarreau8638f482012-09-18 18:01:17 +02002966 err = NULL;
2967 if (!bind_dumped) {
2968 bind_dump_kws(&err);
2969 indent_msg(&err, 4);
2970 bind_dumped = 1;
2971 }
2972
2973 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2974 file, linenum, args[0], args[1], args[cur_arg],
2975 err ? " Registered keywords :" : "", err ? err : "");
2976 free(err);
2977
Willy Tarreau93893792009-07-23 13:19:11 +02002978 err_code |= ERR_ALERT | ERR_FATAL;
2979 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002980 }
Willy Tarreau93893792009-07-23 13:19:11 +02002981 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002982 }
2983 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002984 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002985 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2986 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002987 err_code |= ERR_ALERT | ERR_FATAL;
2988 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002989 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002990 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002991 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002992
Willy Tarreaubaaee002006-06-26 02:48:02 +02002993 /* flush useless bits */
2994 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002995 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002996 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002997 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002998 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002999 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003000
William Lallemanddf1425a2015-04-28 20:17:49 +02003001 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3002 goto out;
3003
Willy Tarreau1c47f852006-07-09 08:22:27 +02003004 if (!*args[1]) {
3005 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
3006 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003007 err_code |= ERR_ALERT | ERR_FATAL;
3008 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003009 }
3010
Willy Tarreaua534fea2008-08-03 12:19:50 +02003011 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003012 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02003013 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003014 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02003015 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
3016
Willy Tarreau93893792009-07-23 13:19:11 +02003017 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003018 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003019 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
William Lallemanddf1425a2015-04-28 20:17:49 +02003020 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3021 goto out;
3022
Willy Tarreaubaaee002006-06-26 02:48:02 +02003023 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
3024 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
3025 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
3026 else {
3027 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003028 err_code |= ERR_ALERT | ERR_FATAL;
3029 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003030 }
3031 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003032 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003033 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003034
3035 if (curproxy == &defproxy) {
3036 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3037 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003038 err_code |= ERR_ALERT | ERR_FATAL;
3039 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003040 }
3041
William Lallemanddf1425a2015-04-28 20:17:49 +02003042 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3043 goto out;
3044
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003045 if (!*args[1]) {
3046 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3047 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003048 err_code |= ERR_ALERT | ERR_FATAL;
3049 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003050 }
3051
3052 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003053 curproxy->conf.id.key = curproxy->uuid;
Willy Tarreau0d1fdf72015-05-27 16:44:02 +02003054 curproxy->options |= PR_O_FORCED_ID;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003055
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003056 if (curproxy->uuid <= 0) {
3057 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003058 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003059 err_code |= ERR_ALERT | ERR_FATAL;
3060 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003061 }
3062
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003063 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
3064 if (node) {
3065 struct proxy *target = container_of(node, struct proxy, conf.id);
3066 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
3067 file, linenum, proxy_type_str(curproxy), curproxy->id,
3068 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
3069 err_code |= ERR_ALERT | ERR_FATAL;
3070 goto out;
3071 }
3072 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003073 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003074 else if (!strcmp(args[0], "description")) {
3075 int i, len=0;
3076 char *d;
3077
Cyril Bonté99ed3272010-01-24 23:29:44 +01003078 if (curproxy == &defproxy) {
3079 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3080 file, linenum, args[0]);
3081 err_code |= ERR_ALERT | ERR_FATAL;
3082 goto out;
3083 }
3084
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003085 if (!*args[1]) {
3086 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
3087 file, linenum, args[0]);
3088 return -1;
3089 }
3090
Willy Tarreau348acfe2014-04-14 15:00:39 +02003091 for (i = 1; *args[i]; i++)
3092 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003093
3094 d = (char *)calloc(1, len);
3095 curproxy->desc = d;
3096
Willy Tarreau348acfe2014-04-14 15:00:39 +02003097 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
3098 for (i = 2; *args[i]; i++)
3099 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003100
3101 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003102 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
William Lallemanddf1425a2015-04-28 20:17:49 +02003103 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3104 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003105 curproxy->state = PR_STSTOPPED;
3106 }
3107 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
William Lallemanddf1425a2015-04-28 20:17:49 +02003108 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3109 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003110 curproxy->state = PR_STNEW;
3111 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003112 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
3113 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003114 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003115
3116 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003117 unsigned int low, high;
3118
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003119 if (strcmp(args[cur_arg], "all") == 0) {
3120 set = 0;
3121 break;
3122 }
3123 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003124 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003125 }
3126 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003127 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003128 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01003129 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003130 char *dash = strchr(args[cur_arg], '-');
3131
3132 low = high = str2uic(args[cur_arg]);
3133 if (dash)
3134 high = str2uic(dash + 1);
3135
3136 if (high < low) {
3137 unsigned int swap = low;
3138 low = high;
3139 high = swap;
3140 }
3141
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003142 if (low < 1 || high > LONGBITS) {
3143 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
3144 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02003145 err_code |= ERR_ALERT | ERR_FATAL;
3146 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003147 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01003148 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003149 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003150 }
3151 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003152 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
3153 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003154 err_code |= ERR_ALERT | ERR_FATAL;
3155 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003156 }
3157 cur_arg++;
3158 }
3159 curproxy->bind_proc = set;
3160 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003161 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02003162 if (curproxy == &defproxy) {
3163 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003164 err_code |= ERR_ALERT | ERR_FATAL;
3165 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003166 }
3167
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003168 err = invalid_char(args[1]);
3169 if (err) {
3170 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
3171 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003172 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003173 }
3174
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01003175 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003176 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
3177 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003178 err_code |= ERR_ALERT | ERR_FATAL;
3179 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003180 }
3181 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003182 else if (!strcmp(args[0], "cookie")) { /* cookie name */
3183 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003184
Willy Tarreau977b8e42006-12-29 14:19:17 +01003185 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003186 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003187
Willy Tarreaubaaee002006-06-26 02:48:02 +02003188 if (*(args[1]) == 0) {
3189 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
3190 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003191 err_code |= ERR_ALERT | ERR_FATAL;
3192 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003193 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003194
Willy Tarreau67402132012-05-31 20:40:20 +02003195 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003196 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01003197 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003198 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003199 curproxy->cookie_name = strdup(args[1]);
3200 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003201
Willy Tarreaubaaee002006-06-26 02:48:02 +02003202 cur_arg = 2;
3203 while (*(args[cur_arg])) {
3204 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003205 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003206 }
3207 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003208 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003209 }
3210 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003211 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003212 }
3213 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003214 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003215 }
3216 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003217 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003218 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003219 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003220 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003221 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003222 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003223 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003224 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02003225 else if (!strcmp(args[cur_arg], "httponly")) {
3226 curproxy->ck_opts |= PR_CK_HTTPONLY;
3227 }
3228 else if (!strcmp(args[cur_arg], "secure")) {
3229 curproxy->ck_opts |= PR_CK_SECURE;
3230 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003231 else if (!strcmp(args[cur_arg], "domain")) {
3232 if (!*args[cur_arg + 1]) {
3233 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
3234 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003235 err_code |= ERR_ALERT | ERR_FATAL;
3236 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003237 }
3238
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003239 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003240 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003241 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
3242 " dots nor does not start with a dot."
3243 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003244 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003245 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003246 }
3247
3248 err = invalid_domainchar(args[cur_arg + 1]);
3249 if (err) {
3250 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
3251 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003252 err_code |= ERR_ALERT | ERR_FATAL;
3253 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003254 }
3255
Willy Tarreau68a897b2009-12-03 23:28:34 +01003256 if (!curproxy->cookie_domain) {
3257 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
3258 } else {
3259 /* one domain was already specified, add another one by
3260 * building the string which will be returned along with
3261 * the cookie.
3262 */
3263 char *new_ptr;
3264 int new_len = strlen(curproxy->cookie_domain) +
3265 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
3266 new_ptr = malloc(new_len);
3267 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
3268 free(curproxy->cookie_domain);
3269 curproxy->cookie_domain = new_ptr;
3270 }
Willy Tarreau31936852010-10-06 16:59:56 +02003271 cur_arg++;
3272 }
3273 else if (!strcmp(args[cur_arg], "maxidle")) {
3274 unsigned int maxidle;
3275 const char *res;
3276
3277 if (!*args[cur_arg + 1]) {
3278 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
3279 file, linenum, args[cur_arg]);
3280 err_code |= ERR_ALERT | ERR_FATAL;
3281 goto out;
3282 }
3283
3284 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
3285 if (res) {
3286 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3287 file, linenum, *res, args[cur_arg]);
3288 err_code |= ERR_ALERT | ERR_FATAL;
3289 goto out;
3290 }
3291 curproxy->cookie_maxidle = maxidle;
3292 cur_arg++;
3293 }
3294 else if (!strcmp(args[cur_arg], "maxlife")) {
3295 unsigned int maxlife;
3296 const char *res;
3297
3298 if (!*args[cur_arg + 1]) {
3299 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
3300 file, linenum, args[cur_arg]);
3301 err_code |= ERR_ALERT | ERR_FATAL;
3302 goto out;
3303 }
3304
3305 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
3306 if (res) {
3307 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3308 file, linenum, *res, args[cur_arg]);
3309 err_code |= ERR_ALERT | ERR_FATAL;
3310 goto out;
3311 }
3312 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003313 cur_arg++;
3314 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003315 else {
Willy Tarreau31936852010-10-06 16:59:56 +02003316 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 +02003317 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003318 err_code |= ERR_ALERT | ERR_FATAL;
3319 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003320 }
3321 cur_arg++;
3322 }
Willy Tarreau67402132012-05-31 20:40:20 +02003323 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003324 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
3325 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003326 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003327 }
3328
Willy Tarreau67402132012-05-31 20:40:20 +02003329 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003330 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
3331 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003332 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003333 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003334
Willy Tarreau67402132012-05-31 20:40:20 +02003335 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003336 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
3337 file, linenum);
3338 err_code |= ERR_ALERT | ERR_FATAL;
3339 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003340 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09003341 else if (!strcmp(args[0], "email-alert")) {
3342 if (*(args[1]) == 0) {
3343 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3344 file, linenum, args[0]);
3345 err_code |= ERR_ALERT | ERR_FATAL;
3346 goto out;
3347 }
3348
3349 if (!strcmp(args[1], "from")) {
3350 if (*(args[1]) == 0) {
3351 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3352 file, linenum, args[1]);
3353 err_code |= ERR_ALERT | ERR_FATAL;
3354 goto out;
3355 }
3356 free(curproxy->email_alert.from);
3357 curproxy->email_alert.from = strdup(args[2]);
3358 }
3359 else if (!strcmp(args[1], "mailers")) {
3360 if (*(args[1]) == 0) {
3361 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3362 file, linenum, args[1]);
3363 err_code |= ERR_ALERT | ERR_FATAL;
3364 goto out;
3365 }
3366 free(curproxy->email_alert.mailers.name);
3367 curproxy->email_alert.mailers.name = strdup(args[2]);
3368 }
3369 else if (!strcmp(args[1], "myhostname")) {
3370 if (*(args[1]) == 0) {
3371 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3372 file, linenum, args[1]);
3373 err_code |= ERR_ALERT | ERR_FATAL;
3374 goto out;
3375 }
3376 free(curproxy->email_alert.myhostname);
3377 curproxy->email_alert.myhostname = strdup(args[2]);
3378 }
Simon Horman64e34162015-02-06 11:11:57 +09003379 else if (!strcmp(args[1], "level")) {
3380 curproxy->email_alert.level = get_log_level(args[2]);
3381 if (curproxy->email_alert.level < 0) {
3382 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
3383 file, linenum, args[1], args[2]);
3384 err_code |= ERR_ALERT | ERR_FATAL;
3385 goto out;
3386 }
3387 }
Simon Horman9dc49962015-01-30 11:22:59 +09003388 else if (!strcmp(args[1], "to")) {
3389 if (*(args[1]) == 0) {
3390 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3391 file, linenum, args[1]);
3392 err_code |= ERR_ALERT | ERR_FATAL;
3393 goto out;
3394 }
3395 free(curproxy->email_alert.to);
3396 curproxy->email_alert.to = strdup(args[2]);
3397 }
3398 else {
3399 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
3400 file, linenum, args[1]);
3401 err_code |= ERR_ALERT | ERR_FATAL;
3402 goto out;
3403 }
Simon Horman64e34162015-02-06 11:11:57 +09003404 /* Indicate that the email_alert is at least partially configured */
3405 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09003406 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09003407 else if (!strcmp(args[0], "external-check")) {
3408 if (*(args[1]) == 0) {
3409 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3410 file, linenum, args[0]);
3411 err_code |= ERR_ALERT | ERR_FATAL;
3412 goto out;
3413 }
3414
3415 if (!strcmp(args[1], "command")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003416 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003417 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003418 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003419 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3420 file, linenum, args[1]);
3421 err_code |= ERR_ALERT | ERR_FATAL;
3422 goto out;
3423 }
3424 free(curproxy->check_command);
3425 curproxy->check_command = strdup(args[2]);
3426 }
3427 else if (!strcmp(args[1], "path")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003428 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003429 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003430 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003431 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3432 file, linenum, args[1]);
3433 err_code |= ERR_ALERT | ERR_FATAL;
3434 goto out;
3435 }
3436 free(curproxy->check_path);
3437 curproxy->check_path = strdup(args[2]);
3438 }
3439 else {
3440 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
3441 file, linenum, args[1]);
3442 err_code |= ERR_ALERT | ERR_FATAL;
3443 goto out;
3444 }
3445 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02003446 else if (!strcmp(args[0], "persist")) { /* persist */
3447 if (*(args[1]) == 0) {
3448 Alert("parsing [%s:%d] : missing persist method.\n",
3449 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003450 err_code |= ERR_ALERT | ERR_FATAL;
3451 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003452 }
3453
3454 if (!strncmp(args[1], "rdp-cookie", 10)) {
3455 curproxy->options2 |= PR_O2_RDPC_PRST;
3456
Emeric Brunb982a3d2010-01-04 15:45:53 +01003457 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003458 const char *beg, *end;
3459
3460 beg = args[1] + 11;
3461 end = strchr(beg, ')');
3462
William Lallemanddf1425a2015-04-28 20:17:49 +02003463 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3464 goto out;
3465
Emeric Brun647caf12009-06-30 17:57:00 +02003466 if (!end || end == beg) {
3467 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3468 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003469 err_code |= ERR_ALERT | ERR_FATAL;
3470 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003471 }
3472
3473 free(curproxy->rdp_cookie_name);
3474 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3475 curproxy->rdp_cookie_len = end-beg;
3476 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003477 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003478 free(curproxy->rdp_cookie_name);
3479 curproxy->rdp_cookie_name = strdup("msts");
3480 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3481 }
3482 else { /* syntax */
3483 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3484 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003485 err_code |= ERR_ALERT | ERR_FATAL;
3486 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003487 }
3488 }
3489 else {
3490 Alert("parsing [%s:%d] : unknown persist method.\n",
3491 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003492 err_code |= ERR_ALERT | ERR_FATAL;
3493 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003494 }
3495 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003496 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreau6db62c52015-08-10 19:04:29 +02003497 Alert("parsing [%s:%d] : '%s' is not supported anymore, please check the documentation.\n", file, linenum, args[0]);
3498 err_code |= ERR_ALERT | ERR_FATAL;
3499 goto out;
3500 }
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02003501 else if (!strcmp(args[0], "load-server-state-from-file")) {
3502 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3503 err_code |= ERR_WARN;
3504 if (!strcmp(args[1], "global")) { /* use the file pointed to by global server-state-file directive */
3505 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_GLOBAL;
3506 }
3507 else if (!strcmp(args[1], "local")) { /* use the server-state-file-name variable to locate the server-state file */
3508 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_LOCAL;
3509 }
3510 else if (!strcmp(args[1], "none")) { /* don't use server-state-file directive for this backend */
3511 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
3512 }
3513 else {
3514 Alert("parsing [%s:%d] : '%s' expects 'global', 'local' or 'none'. Got '%s'\n",
3515 file, linenum, args[0], args[1]);
3516 err_code |= ERR_ALERT | ERR_FATAL;
3517 goto out;
3518 }
3519 }
3520 else if (!strcmp(args[0], "server-state-file-name")) {
3521 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3522 err_code |= ERR_WARN;
3523 if (*(args[1]) == 0) {
3524 Alert("parsing [%s:%d] : '%s' expects 'use-backend-name' or a string. Got no argument\n",
3525 file, linenum, args[0]);
3526 err_code |= ERR_ALERT | ERR_FATAL;
3527 goto out;
3528 }
3529 else if (!strcmp(args[1], "use-backend-name"))
3530 curproxy->server_state_file_name = strdup(curproxy->id);
3531 else
3532 curproxy->server_state_file_name = strdup(args[1]);
3533 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003534 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003535 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003536 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003537
Willy Tarreaubaaee002006-06-26 02:48:02 +02003538 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003539 if (curproxy == &defproxy) {
3540 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3541 err_code |= ERR_ALERT | ERR_FATAL;
3542 goto out;
3543 }
3544
William Lallemand1a748ae2015-05-19 16:37:23 +02003545 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3546 goto out;
3547
Willy Tarreaubaaee002006-06-26 02:48:02 +02003548 if (*(args[4]) == 0) {
3549 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3550 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003551 err_code |= ERR_ALERT | ERR_FATAL;
3552 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003553 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003554 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003555 curproxy->capture_name = strdup(args[2]);
3556 curproxy->capture_namelen = strlen(curproxy->capture_name);
3557 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003558 curproxy->to_log |= LW_COOKIE;
3559 }
3560 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3561 struct cap_hdr *hdr;
3562
3563 if (curproxy == &defproxy) {
3564 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 +02003565 err_code |= ERR_ALERT | ERR_FATAL;
3566 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003567 }
3568
William Lallemand1a748ae2015-05-19 16:37:23 +02003569 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3570 goto out;
3571
Willy Tarreaubaaee002006-06-26 02:48:02 +02003572 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3573 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3574 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003575 err_code |= ERR_ALERT | ERR_FATAL;
3576 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003577 }
3578
3579 hdr = calloc(sizeof(struct cap_hdr), 1);
3580 hdr->next = curproxy->req_cap;
3581 hdr->name = strdup(args[3]);
3582 hdr->namelen = strlen(args[3]);
3583 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003584 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003585 hdr->index = curproxy->nb_req_cap++;
3586 curproxy->req_cap = hdr;
3587 curproxy->to_log |= LW_REQHDR;
3588 }
3589 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3590 struct cap_hdr *hdr;
3591
3592 if (curproxy == &defproxy) {
3593 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 +02003594 err_code |= ERR_ALERT | ERR_FATAL;
3595 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003596 }
3597
William Lallemand1a748ae2015-05-19 16:37:23 +02003598 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3599 goto out;
3600
Willy Tarreaubaaee002006-06-26 02:48:02 +02003601 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3602 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3603 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003604 err_code |= ERR_ALERT | ERR_FATAL;
3605 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003606 }
3607 hdr = calloc(sizeof(struct cap_hdr), 1);
3608 hdr->next = curproxy->rsp_cap;
3609 hdr->name = strdup(args[3]);
3610 hdr->namelen = strlen(args[3]);
3611 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003612 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003613 hdr->index = curproxy->nb_rsp_cap++;
3614 curproxy->rsp_cap = hdr;
3615 curproxy->to_log |= LW_RSPHDR;
3616 }
3617 else {
3618 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3619 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003620 err_code |= ERR_ALERT | ERR_FATAL;
3621 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003622 }
3623 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003624 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003625 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003626 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003627
William Lallemanddf1425a2015-04-28 20:17:49 +02003628 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3629 goto out;
3630
Willy Tarreaubaaee002006-06-26 02:48:02 +02003631 if (*(args[1]) == 0) {
3632 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3633 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003634 err_code |= ERR_ALERT | ERR_FATAL;
3635 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003636 }
3637 curproxy->conn_retries = atol(args[1]);
3638 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003639 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003640 struct act_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003641
3642 if (curproxy == &defproxy) {
3643 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3644 err_code |= ERR_ALERT | ERR_FATAL;
3645 goto out;
3646 }
3647
Willy Tarreau20b0de52012-12-24 15:45:22 +01003648 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003649 !LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003650 (LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3651 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_DENY ||
3652 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REDIR ||
3653 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REQ_AUTH)) {
Willy Tarreau20b0de52012-12-24 15:45:22 +01003654 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 +01003655 file, linenum, args[0]);
3656 err_code |= ERR_WARN;
3657 }
3658
Willy Tarreauff011f22011-01-06 17:51:27 +01003659 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003660
Willy Tarreauff011f22011-01-06 17:51:27 +01003661 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003662 err_code |= ERR_ALERT | ERR_ABORT;
3663 goto out;
3664 }
3665
Willy Tarreau5002f572014-04-23 01:32:02 +02003666 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003667 err_code |= warnif_cond_conflicts(rule->cond,
3668 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3669 file, linenum);
3670
Willy Tarreauff011f22011-01-06 17:51:27 +01003671 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003672 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003673 else if (!strcmp(args[0], "http-response")) { /* response access control */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003674 struct act_rule *rule;
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003675
3676 if (curproxy == &defproxy) {
3677 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3678 err_code |= ERR_ALERT | ERR_FATAL;
3679 goto out;
3680 }
3681
3682 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003683 !LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003684 (LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3685 LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_DENY)) {
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003686 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3687 file, linenum, args[0]);
3688 err_code |= ERR_WARN;
3689 }
3690
3691 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3692
3693 if (!rule) {
3694 err_code |= ERR_ALERT | ERR_ABORT;
3695 goto out;
3696 }
3697
3698 err_code |= warnif_cond_conflicts(rule->cond,
3699 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3700 file, linenum);
3701
3702 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3703 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003704 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3705 /* set the header name and length into the proxy structure */
3706 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3707 err_code |= ERR_WARN;
3708
3709 if (!*args[1]) {
3710 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3711 file, linenum, args[0]);
3712 err_code |= ERR_ALERT | ERR_FATAL;
3713 goto out;
3714 }
3715
3716 /* set the desired header name */
3717 free(curproxy->server_id_hdr_name);
3718 curproxy->server_id_hdr_name = strdup(args[1]);
3719 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3720 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003721 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003722 struct act_rule *rule;
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003723
Willy Tarreaub099aca2008-10-12 17:26:37 +02003724 if (curproxy == &defproxy) {
3725 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003726 err_code |= ERR_ALERT | ERR_FATAL;
3727 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003728 }
3729
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003730 /* emulate "block" using "http-request block". Since these rules are supposed to
3731 * be processed before all http-request rules, we put them into their own list
3732 * and will insert them at the end.
3733 */
3734 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3735 if (!rule) {
3736 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003737 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003738 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003739 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3740 err_code |= warnif_cond_conflicts(rule->cond,
3741 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3742 file, linenum);
3743 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003744
3745 if (!already_warned(WARN_BLOCK_DEPRECATED))
3746 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]);
3747
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003748 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003749 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003750 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003751
Cyril Bonté99ed3272010-01-24 23:29:44 +01003752 if (curproxy == &defproxy) {
3753 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3754 err_code |= ERR_ALERT | ERR_FATAL;
3755 goto out;
3756 }
3757
Willy Tarreaube4653b2015-05-28 15:26:58 +02003758 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003759 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3760 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003761 err_code |= ERR_ALERT | ERR_FATAL;
3762 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003763 }
3764
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003765 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003766 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003767 err_code |= warnif_cond_conflicts(rule->cond,
3768 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3769 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003770 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003771 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003772 struct switching_rule *rule;
3773
Willy Tarreaub099aca2008-10-12 17:26:37 +02003774 if (curproxy == &defproxy) {
3775 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003776 err_code |= ERR_ALERT | ERR_FATAL;
3777 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003778 }
3779
Willy Tarreau55ea7572007-06-17 19:56:27 +02003780 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003781 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003782
3783 if (*(args[1]) == 0) {
3784 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003785 err_code |= ERR_ALERT | ERR_FATAL;
3786 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003787 }
3788
Willy Tarreauf51658d2014-04-23 01:21:56 +02003789 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3790 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3791 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3792 file, linenum, errmsg);
3793 err_code |= ERR_ALERT | ERR_FATAL;
3794 goto out;
3795 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003796
Willy Tarreauf51658d2014-04-23 01:21:56 +02003797 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003798 }
3799
3800 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
3801 rule->cond = cond;
3802 rule->be.name = strdup(args[1]);
3803 LIST_INIT(&rule->list);
3804 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3805 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003806 else if (strcmp(args[0], "use-server") == 0) {
3807 struct server_rule *rule;
3808
3809 if (curproxy == &defproxy) {
3810 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3811 err_code |= ERR_ALERT | ERR_FATAL;
3812 goto out;
3813 }
3814
3815 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3816 err_code |= ERR_WARN;
3817
3818 if (*(args[1]) == 0) {
3819 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3820 err_code |= ERR_ALERT | ERR_FATAL;
3821 goto out;
3822 }
3823
3824 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3825 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3826 file, linenum, args[0]);
3827 err_code |= ERR_ALERT | ERR_FATAL;
3828 goto out;
3829 }
3830
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003831 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3832 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3833 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003834 err_code |= ERR_ALERT | ERR_FATAL;
3835 goto out;
3836 }
3837
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003838 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003839
3840 rule = (struct server_rule *)calloc(1, sizeof(*rule));
3841 rule->cond = cond;
3842 rule->srv.name = strdup(args[1]);
3843 LIST_INIT(&rule->list);
3844 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3845 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3846 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003847 else if ((!strcmp(args[0], "force-persist")) ||
3848 (!strcmp(args[0], "ignore-persist"))) {
3849 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003850
3851 if (curproxy == &defproxy) {
3852 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3853 err_code |= ERR_ALERT | ERR_FATAL;
3854 goto out;
3855 }
3856
3857 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3858 err_code |= ERR_WARN;
3859
Willy Tarreauef6494c2010-01-28 17:12:36 +01003860 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003861 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3862 file, linenum, args[0]);
3863 err_code |= ERR_ALERT | ERR_FATAL;
3864 goto out;
3865 }
3866
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003867 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3868 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3869 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003870 err_code |= ERR_ALERT | ERR_FATAL;
3871 goto out;
3872 }
3873
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003874 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3875 * where force-persist is applied.
3876 */
3877 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003878
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003879 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003880 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003881 if (!strcmp(args[0], "force-persist")) {
3882 rule->type = PERSIST_TYPE_FORCE;
3883 } else {
3884 rule->type = PERSIST_TYPE_IGNORE;
3885 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003886 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003887 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003888 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003889 else if (!strcmp(args[0], "stick-table")) {
3890 int myidx = 1;
Willy Tarreaue45288c2015-05-26 10:49:46 +02003891 struct proxy *other;
3892
Willy Tarreaue2dc1fa2015-05-26 12:08:07 +02003893 other = proxy_tbl_by_name(curproxy->id);
Willy Tarreaue45288c2015-05-26 10:49:46 +02003894 if (other) {
3895 Alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
3896 file, linenum, curproxy->id, proxy_type_str(other), other->id, other->conf.file, other->conf.line);
3897 err_code |= ERR_ALERT | ERR_FATAL;
3898 goto out;
3899 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003900
Emeric Brun32da3c42010-09-23 18:39:19 +02003901 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003902 curproxy->table.type = (unsigned int)-1;
3903 while (*args[myidx]) {
3904 const char *err;
3905
3906 if (strcmp(args[myidx], "size") == 0) {
3907 myidx++;
3908 if (!*(args[myidx])) {
3909 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3910 file, linenum, args[myidx-1]);
3911 err_code |= ERR_ALERT | ERR_FATAL;
3912 goto out;
3913 }
3914 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3915 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3916 file, linenum, *err, args[myidx-1]);
3917 err_code |= ERR_ALERT | ERR_FATAL;
3918 goto out;
3919 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003920 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003921 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003922 else if (strcmp(args[myidx], "peers") == 0) {
3923 myidx++;
Godbach50523162013-12-11 19:48:57 +08003924 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003925 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3926 file, linenum, args[myidx-1]);
3927 err_code |= ERR_ALERT | ERR_FATAL;
3928 goto out;
Godbach50523162013-12-11 19:48:57 +08003929 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003930 curproxy->table.peers.name = strdup(args[myidx++]);
3931 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003932 else if (strcmp(args[myidx], "expire") == 0) {
3933 myidx++;
3934 if (!*(args[myidx])) {
3935 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3936 file, linenum, args[myidx-1]);
3937 err_code |= ERR_ALERT | ERR_FATAL;
3938 goto out;
3939 }
3940 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3941 if (err) {
3942 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3943 file, linenum, *err, args[myidx-1]);
3944 err_code |= ERR_ALERT | ERR_FATAL;
3945 goto out;
3946 }
3947 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003948 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003949 }
3950 else if (strcmp(args[myidx], "nopurge") == 0) {
3951 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003952 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003953 }
3954 else if (strcmp(args[myidx], "type") == 0) {
3955 myidx++;
3956 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3957 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3958 file, linenum, args[myidx]);
3959 err_code |= ERR_ALERT | ERR_FATAL;
3960 goto out;
3961 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003962 /* myidx already points to next arg */
3963 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003964 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003965 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003966 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003967
3968 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003969 nw = args[myidx];
3970 while (*nw) {
3971 /* the "store" keyword supports a comma-separated list */
3972 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003973 sa = NULL; /* store arg */
3974 while (*nw && *nw != ',') {
3975 if (*nw == '(') {
3976 *nw = 0;
3977 sa = ++nw;
3978 while (*nw != ')') {
3979 if (!*nw) {
3980 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3981 file, linenum, args[0], cw);
3982 err_code |= ERR_ALERT | ERR_FATAL;
3983 goto out;
3984 }
3985 nw++;
3986 }
3987 *nw = '\0';
3988 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003989 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003990 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003991 if (*nw)
3992 *nw++ = '\0';
3993 type = stktable_get_data_type(cw);
3994 if (type < 0) {
3995 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3996 file, linenum, args[0], cw);
3997 err_code |= ERR_ALERT | ERR_FATAL;
3998 goto out;
3999 }
Willy Tarreauac782882010-06-20 10:41:54 +02004000
4001 err = stktable_alloc_data_type(&curproxy->table, type, sa);
4002 switch (err) {
4003 case PE_NONE: break;
4004 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004005 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
4006 file, linenum, args[0], cw);
4007 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02004008 break;
4009
4010 case PE_ARG_MISSING:
4011 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
4012 file, linenum, args[0], cw);
4013 err_code |= ERR_ALERT | ERR_FATAL;
4014 goto out;
4015
4016 case PE_ARG_NOT_USED:
4017 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
4018 file, linenum, args[0], cw);
4019 err_code |= ERR_ALERT | ERR_FATAL;
4020 goto out;
4021
4022 default:
4023 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
4024 file, linenum, args[0], cw);
4025 err_code |= ERR_ALERT | ERR_FATAL;
4026 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004027 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004028 }
4029 myidx++;
4030 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004031 else {
4032 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
4033 file, linenum, args[myidx]);
4034 err_code |= ERR_ALERT | ERR_FATAL;
4035 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004036 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004037 }
4038
4039 if (!curproxy->table.size) {
4040 Alert("parsing [%s:%d] : stick-table: missing size.\n",
4041 file, linenum);
4042 err_code |= ERR_ALERT | ERR_FATAL;
4043 goto out;
4044 }
4045
4046 if (curproxy->table.type == (unsigned int)-1) {
4047 Alert("parsing [%s:%d] : stick-table: missing type.\n",
4048 file, linenum);
4049 err_code |= ERR_ALERT | ERR_FATAL;
4050 goto out;
4051 }
4052 }
4053 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004054 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02004055 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004056 int myidx = 0;
4057 const char *name = NULL;
4058 int flags;
4059
4060 if (curproxy == &defproxy) {
4061 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4062 err_code |= ERR_ALERT | ERR_FATAL;
4063 goto out;
4064 }
4065
4066 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
4067 err_code |= ERR_WARN;
4068 goto out;
4069 }
4070
4071 myidx++;
4072 if ((strcmp(args[myidx], "store") == 0) ||
4073 (strcmp(args[myidx], "store-request") == 0)) {
4074 myidx++;
4075 flags = STK_IS_STORE;
4076 }
4077 else if (strcmp(args[myidx], "store-response") == 0) {
4078 myidx++;
4079 flags = STK_IS_STORE | STK_ON_RSP;
4080 }
4081 else if (strcmp(args[myidx], "match") == 0) {
4082 myidx++;
4083 flags = STK_IS_MATCH;
4084 }
4085 else if (strcmp(args[myidx], "on") == 0) {
4086 myidx++;
4087 flags = STK_IS_MATCH | STK_IS_STORE;
4088 }
4089 else {
4090 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
4091 err_code |= ERR_ALERT | ERR_FATAL;
4092 goto out;
4093 }
4094
4095 if (*(args[myidx]) == 0) {
4096 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
4097 err_code |= ERR_ALERT | ERR_FATAL;
4098 goto out;
4099 }
4100
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004101 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01004102 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004103 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01004104 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004105 err_code |= ERR_ALERT | ERR_FATAL;
4106 goto out;
4107 }
4108
4109 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01004110 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
4111 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
4112 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004113 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004114 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004115 goto out;
4116 }
4117 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01004118 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
4119 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
4120 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004121 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004122 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004123 goto out;
4124 }
4125 }
4126
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004127 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01004128 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004129
Emeric Brunb982a3d2010-01-04 15:45:53 +01004130 if (strcmp(args[myidx], "table") == 0) {
4131 myidx++;
4132 name = args[myidx++];
4133 }
4134
Willy Tarreauef6494c2010-01-28 17:12:36 +01004135 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004136 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
4137 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
4138 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004139 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004140 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004141 goto out;
4142 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004143 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01004144 else if (*(args[myidx])) {
4145 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
4146 file, linenum, args[0], args[myidx]);
4147 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004148 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01004149 goto out;
4150 }
Emeric Brun97679e72010-09-23 17:56:44 +02004151 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004152 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02004153 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004154 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01004155
Emeric Brunb982a3d2010-01-04 15:45:53 +01004156 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
4157 rule->cond = cond;
4158 rule->expr = expr;
4159 rule->flags = flags;
4160 rule->table.name = name ? strdup(name) : NULL;
4161 LIST_INIT(&rule->list);
4162 if (flags & STK_ON_RSP)
4163 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
4164 else
4165 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
4166 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004167 else if (!strcmp(args[0], "stats")) {
4168 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
4169 curproxy->uri_auth = NULL; /* we must detach from the default config */
4170
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004171 if (!*args[1]) {
4172 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02004173 } else if (!strcmp(args[1], "admin")) {
4174 struct stats_admin_rule *rule;
4175
4176 if (curproxy == &defproxy) {
4177 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
4178 err_code |= ERR_ALERT | ERR_FATAL;
4179 goto out;
4180 }
4181
4182 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4183 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4184 err_code |= ERR_ALERT | ERR_ABORT;
4185 goto out;
4186 }
4187
4188 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4189 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4190 file, linenum, args[0], args[1]);
4191 err_code |= ERR_ALERT | ERR_FATAL;
4192 goto out;
4193 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004194 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4195 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
4196 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02004197 err_code |= ERR_ALERT | ERR_FATAL;
4198 goto out;
4199 }
4200
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004201 err_code |= warnif_cond_conflicts(cond,
4202 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4203 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02004204
4205 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
4206 rule->cond = cond;
4207 LIST_INIT(&rule->list);
4208 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004209 } else if (!strcmp(args[1], "uri")) {
4210 if (*(args[2]) == 0) {
4211 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004212 err_code |= ERR_ALERT | ERR_FATAL;
4213 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004214 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
4215 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004216 err_code |= ERR_ALERT | ERR_ABORT;
4217 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004218 }
4219 } else if (!strcmp(args[1], "realm")) {
4220 if (*(args[2]) == 0) {
4221 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004222 err_code |= ERR_ALERT | ERR_FATAL;
4223 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004224 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
4225 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004226 err_code |= ERR_ALERT | ERR_ABORT;
4227 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004228 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02004229 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004230 unsigned interval;
4231
4232 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
4233 if (err) {
4234 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
4235 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004236 err_code |= ERR_ALERT | ERR_FATAL;
4237 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004238 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
4239 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004240 err_code |= ERR_ALERT | ERR_ABORT;
4241 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004242 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004243 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004244 struct act_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004245
4246 if (curproxy == &defproxy) {
4247 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4248 err_code |= ERR_ALERT | ERR_FATAL;
4249 goto out;
4250 }
4251
4252 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4253 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4254 err_code |= ERR_ALERT | ERR_ABORT;
4255 goto out;
4256 }
4257
Willy Tarreauff011f22011-01-06 17:51:27 +01004258 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004259 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct act_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004260 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
4261 file, linenum, args[0]);
4262 err_code |= ERR_WARN;
4263 }
4264
Willy Tarreauff011f22011-01-06 17:51:27 +01004265 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004266
Willy Tarreauff011f22011-01-06 17:51:27 +01004267 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004268 err_code |= ERR_ALERT | ERR_ABORT;
4269 goto out;
4270 }
4271
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004272 err_code |= warnif_cond_conflicts(rule->cond,
4273 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4274 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01004275 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004276
Willy Tarreaubaaee002006-06-26 02:48:02 +02004277 } else if (!strcmp(args[1], "auth")) {
4278 if (*(args[2]) == 0) {
4279 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004280 err_code |= ERR_ALERT | ERR_FATAL;
4281 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004282 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
4283 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004284 err_code |= ERR_ALERT | ERR_ABORT;
4285 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004286 }
4287 } else if (!strcmp(args[1], "scope")) {
4288 if (*(args[2]) == 0) {
4289 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004290 err_code |= ERR_ALERT | ERR_FATAL;
4291 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004292 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
4293 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004294 err_code |= ERR_ALERT | ERR_ABORT;
4295 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004296 }
4297 } else if (!strcmp(args[1], "enable")) {
4298 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4299 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004300 err_code |= ERR_ALERT | ERR_ABORT;
4301 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004302 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004303 } else if (!strcmp(args[1], "hide-version")) {
4304 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
4305 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004306 err_code |= ERR_ALERT | ERR_ABORT;
4307 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004308 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01004309 } else if (!strcmp(args[1], "show-legends")) {
4310 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
4311 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4312 err_code |= ERR_ALERT | ERR_ABORT;
4313 goto out;
4314 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004315 } else if (!strcmp(args[1], "show-node")) {
4316
4317 if (*args[2]) {
4318 int i;
4319 char c;
4320
4321 for (i=0; args[2][i]; i++) {
4322 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01004323 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
4324 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004325 break;
4326 }
4327
4328 if (!i || args[2][i]) {
4329 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
4330 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
4331 file, linenum, args[0], args[1]);
4332 err_code |= ERR_ALERT | ERR_FATAL;
4333 goto out;
4334 }
4335 }
4336
4337 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
4338 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4339 err_code |= ERR_ALERT | ERR_ABORT;
4340 goto out;
4341 }
4342 } else if (!strcmp(args[1], "show-desc")) {
4343 char *desc = NULL;
4344
4345 if (*args[2]) {
4346 int i, len=0;
4347 char *d;
4348
Willy Tarreau348acfe2014-04-14 15:00:39 +02004349 for (i = 2; *args[i]; i++)
4350 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004351
4352 desc = d = (char *)calloc(1, len);
4353
Willy Tarreau348acfe2014-04-14 15:00:39 +02004354 d += snprintf(d, desc + len - d, "%s", args[2]);
4355 for (i = 3; *args[i]; i++)
4356 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004357 }
4358
4359 if (!*args[2] && !global.desc)
4360 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
4361 file, linenum, args[1]);
4362 else {
4363 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
4364 free(desc);
4365 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4366 err_code |= ERR_ALERT | ERR_ABORT;
4367 goto out;
4368 }
4369 free(desc);
4370 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004371 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004372stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02004373 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 +01004374 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004375 err_code |= ERR_ALERT | ERR_FATAL;
4376 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004377 }
4378 }
4379 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004380 int optnum;
4381
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004382 if (*(args[1]) == '\0') {
4383 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
4384 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004385 err_code |= ERR_ALERT | ERR_FATAL;
4386 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004387 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01004388
4389 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
4390 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004391 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
4392 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4393 file, linenum, cfg_opts[optnum].name);
4394 err_code |= ERR_ALERT | ERR_FATAL;
4395 goto out;
4396 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004397 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4398 goto out;
4399
Willy Tarreau93893792009-07-23 13:19:11 +02004400 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
4401 err_code |= ERR_WARN;
4402 goto out;
4403 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004404
Willy Tarreau3842f002009-06-14 11:39:52 +02004405 curproxy->no_options &= ~cfg_opts[optnum].val;
4406 curproxy->options &= ~cfg_opts[optnum].val;
4407
4408 switch (kwm) {
4409 case KWM_STD:
4410 curproxy->options |= cfg_opts[optnum].val;
4411 break;
4412 case KWM_NO:
4413 curproxy->no_options |= cfg_opts[optnum].val;
4414 break;
4415 case KWM_DEF: /* already cleared */
4416 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004417 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004418
Willy Tarreau93893792009-07-23 13:19:11 +02004419 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004420 }
4421 }
4422
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004423 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
4424 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004425 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
4426 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4427 file, linenum, cfg_opts2[optnum].name);
4428 err_code |= ERR_ALERT | ERR_FATAL;
4429 goto out;
4430 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004431 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4432 goto out;
Willy Tarreau93893792009-07-23 13:19:11 +02004433 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4434 err_code |= ERR_WARN;
4435 goto out;
4436 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004437
Willy Tarreau3842f002009-06-14 11:39:52 +02004438 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4439 curproxy->options2 &= ~cfg_opts2[optnum].val;
4440
4441 switch (kwm) {
4442 case KWM_STD:
4443 curproxy->options2 |= cfg_opts2[optnum].val;
4444 break;
4445 case KWM_NO:
4446 curproxy->no_options2 |= cfg_opts2[optnum].val;
4447 break;
4448 case KWM_DEF: /* already cleared */
4449 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004450 }
Willy Tarreau93893792009-07-23 13:19:11 +02004451 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004452 }
4453 }
4454
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004455 /* HTTP options override each other. They can be cancelled using
4456 * "no option xxx" which only switches to default mode if the mode
4457 * was this one (useful for cancelling options set in defaults
4458 * sections).
4459 */
4460 if (strcmp(args[1], "httpclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004461 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4462 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004463 if (kwm == KWM_STD) {
4464 curproxy->options &= ~PR_O_HTTP_MODE;
4465 curproxy->options |= PR_O_HTTP_PCL;
4466 goto out;
4467 }
4468 else if (kwm == KWM_NO) {
4469 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4470 curproxy->options &= ~PR_O_HTTP_MODE;
4471 goto out;
4472 }
4473 }
4474 else if (strcmp(args[1], "forceclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004475 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4476 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004477 if (kwm == KWM_STD) {
4478 curproxy->options &= ~PR_O_HTTP_MODE;
4479 curproxy->options |= PR_O_HTTP_FCL;
4480 goto out;
4481 }
4482 else if (kwm == KWM_NO) {
4483 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4484 curproxy->options &= ~PR_O_HTTP_MODE;
4485 goto out;
4486 }
4487 }
4488 else if (strcmp(args[1], "http-server-close") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004489 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4490 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004491 if (kwm == KWM_STD) {
4492 curproxy->options &= ~PR_O_HTTP_MODE;
4493 curproxy->options |= PR_O_HTTP_SCL;
4494 goto out;
4495 }
4496 else if (kwm == KWM_NO) {
4497 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4498 curproxy->options &= ~PR_O_HTTP_MODE;
4499 goto out;
4500 }
4501 }
4502 else if (strcmp(args[1], "http-keep-alive") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004503 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4504 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004505 if (kwm == KWM_STD) {
4506 curproxy->options &= ~PR_O_HTTP_MODE;
4507 curproxy->options |= PR_O_HTTP_KAL;
4508 goto out;
4509 }
4510 else if (kwm == KWM_NO) {
4511 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4512 curproxy->options &= ~PR_O_HTTP_MODE;
4513 goto out;
4514 }
4515 }
4516 else if (strcmp(args[1], "http-tunnel") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004517 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4518 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004519 if (kwm == KWM_STD) {
4520 curproxy->options &= ~PR_O_HTTP_MODE;
4521 curproxy->options |= PR_O_HTTP_TUN;
4522 goto out;
4523 }
4524 else if (kwm == KWM_NO) {
4525 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4526 curproxy->options &= ~PR_O_HTTP_MODE;
4527 goto out;
4528 }
4529 }
4530
Joseph Lynch726ab712015-05-11 23:25:34 -07004531 /* Redispatch can take an integer argument that control when the
4532 * resispatch occurs. All values are relative to the retries option.
4533 * This can be cancelled using "no option xxx".
4534 */
4535 if (strcmp(args[1], "redispatch") == 0) {
4536 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
4537 err_code |= ERR_WARN;
4538 goto out;
4539 }
4540
4541 curproxy->no_options &= ~PR_O_REDISP;
4542 curproxy->options &= ~PR_O_REDISP;
4543
4544 switch (kwm) {
4545 case KWM_STD:
4546 curproxy->options |= PR_O_REDISP;
4547 curproxy->redispatch_after = -1;
4548 if(*args[2]) {
4549 curproxy->redispatch_after = atol(args[2]);
4550 }
4551 break;
4552 case KWM_NO:
4553 curproxy->no_options |= PR_O_REDISP;
4554 curproxy->redispatch_after = 0;
4555 break;
4556 case KWM_DEF: /* already cleared */
4557 break;
4558 }
4559 goto out;
4560 }
4561
Willy Tarreau3842f002009-06-14 11:39:52 +02004562 if (kwm != KWM_STD) {
4563 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004564 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004565 err_code |= ERR_ALERT | ERR_FATAL;
4566 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004567 }
4568
Emeric Brun3a058f32009-06-30 18:26:00 +02004569 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004570 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004571 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004572 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004573 if (*(args[2]) != '\0') {
4574 if (!strcmp(args[2], "clf")) {
4575 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004576 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004577 } else {
William Lallemand77063bc2015-05-28 18:02:48 +02004578 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004579 err_code |= ERR_ALERT | ERR_FATAL;
4580 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004581 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004582 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
4583 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004584 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004585 if (curproxy->conf.logformat_string != default_http_log_format &&
4586 curproxy->conf.logformat_string != default_tcp_log_format &&
4587 curproxy->conf.logformat_string != clf_http_log_format)
4588 free(curproxy->conf.logformat_string);
4589 curproxy->conf.logformat_string = logformat;
4590
4591 free(curproxy->conf.lfs_file);
4592 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4593 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004594 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004595 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004596 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004597 if (curproxy->conf.logformat_string != default_http_log_format &&
4598 curproxy->conf.logformat_string != default_tcp_log_format &&
4599 curproxy->conf.logformat_string != clf_http_log_format)
4600 free(curproxy->conf.logformat_string);
4601 curproxy->conf.logformat_string = default_tcp_log_format;
4602
4603 free(curproxy->conf.lfs_file);
4604 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4605 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemanddf1425a2015-04-28 20:17:49 +02004606
4607 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4608 goto out;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004609 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004610 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004611 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004612 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004613 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004614
William Lallemanddf1425a2015-04-28 20:17:49 +02004615 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4616 goto out;
4617
Willy Tarreau13943ab2006-12-31 00:24:10 +01004618 if (curproxy->cap & PR_CAP_FE)
4619 curproxy->options |= PR_O_TCP_CLI_KA;
4620 if (curproxy->cap & PR_CAP_BE)
4621 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004622 }
4623 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004624 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004625 err_code |= ERR_WARN;
4626
Willy Tarreaubaaee002006-06-26 02:48:02 +02004627 /* use HTTP request to check servers' health */
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;
4631 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004632 if (!*args[2]) { /* no argument */
4633 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4634 curproxy->check_len = strlen(DEF_CHECK_REQ);
4635 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004636 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004637 curproxy->check_req = (char *)malloc(reqlen);
4638 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004639 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004640 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004641 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004642 if (*args[4])
4643 reqlen += strlen(args[4]);
4644 else
4645 reqlen += strlen("HTTP/1.0");
4646
4647 curproxy->check_req = (char *)malloc(reqlen);
4648 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004649 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004650 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004651 if (alertif_too_many_args_idx(3, 1, file, linenum, args, &err_code))
4652 goto out;
Willy Tarreauf3c69202006-07-09 16:42:34 +02004653 }
4654 else if (!strcmp(args[1], "ssl-hello-chk")) {
4655 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004656 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004657 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004658
Willy Tarreaua534fea2008-08-03 12:19:50 +02004659 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004660 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004661 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004662 curproxy->options2 |= PR_O2_SSL3_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004663
4664 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4665 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004666 }
Willy Tarreau23677902007-05-08 23:50:35 +02004667 else if (!strcmp(args[1], "smtpchk")) {
4668 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004669 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004670 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004671 curproxy->options2 &= ~PR_O2_CHK_ANY;
4672 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004673
4674 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4675 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4676 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4677 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4678 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4679 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
4680 curproxy->check_req = (char *)malloc(reqlen);
4681 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4682 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4683 } else {
4684 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4685 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4686 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4687 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4688 }
4689 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004690 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4691 goto out;
Willy Tarreau23677902007-05-08 23:50:35 +02004692 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004693 else if (!strcmp(args[1], "pgsql-check")) {
4694 /* use PostgreSQL request to check servers' health */
4695 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4696 err_code |= ERR_WARN;
4697
4698 free(curproxy->check_req);
4699 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004700 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004701 curproxy->options2 |= PR_O2_PGSQL_CHK;
4702
4703 if (*(args[2])) {
4704 int cur_arg = 2;
4705
4706 while (*(args[cur_arg])) {
4707 if (strcmp(args[cur_arg], "user") == 0) {
4708 char * packet;
4709 uint32_t packet_len;
4710 uint32_t pv;
4711
4712 /* suboption header - needs additional argument for it */
4713 if (*(args[cur_arg+1]) == 0) {
4714 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4715 file, linenum, args[0], args[1], args[cur_arg]);
4716 err_code |= ERR_ALERT | ERR_FATAL;
4717 goto out;
4718 }
4719
4720 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4721 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4722 pv = htonl(0x30000); /* protocol version 3.0 */
4723
4724 packet = (char*) calloc(1, packet_len);
4725
4726 memcpy(packet + 4, &pv, 4);
4727
4728 /* copy "user" */
4729 memcpy(packet + 8, "user", 4);
4730
4731 /* copy username */
4732 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4733
4734 free(curproxy->check_req);
4735 curproxy->check_req = packet;
4736 curproxy->check_len = packet_len;
4737
4738 packet_len = htonl(packet_len);
4739 memcpy(packet, &packet_len, 4);
4740 cur_arg += 2;
4741 } else {
4742 /* unknown suboption - catchall */
4743 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4744 file, linenum, args[0], args[1]);
4745 err_code |= ERR_ALERT | ERR_FATAL;
4746 goto out;
4747 }
4748 } /* end while loop */
4749 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004750 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4751 goto out;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004752 }
4753
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004754 else if (!strcmp(args[1], "redis-check")) {
4755 /* use REDIS PING request to check servers' health */
4756 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4757 err_code |= ERR_WARN;
4758
4759 free(curproxy->check_req);
4760 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004761 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004762 curproxy->options2 |= PR_O2_REDIS_CHK;
4763
4764 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
4765 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4766 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004767
4768 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4769 goto out;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004770 }
4771
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004772 else if (!strcmp(args[1], "mysql-check")) {
4773 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004774 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4775 err_code |= ERR_WARN;
4776
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004777 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004778 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004779 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004780 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004781
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004782 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004783 * const char mysql40_client_auth_pkt[] = {
4784 * "\x0e\x00\x00" // packet length
4785 * "\x01" // packet number
4786 * "\x00\x00" // client capabilities
4787 * "\x00\x00\x01" // max packet
4788 * "haproxy\x00" // username (null terminated string)
4789 * "\x00" // filler (always 0x00)
4790 * "\x01\x00\x00" // packet length
4791 * "\x00" // packet number
4792 * "\x01" // COM_QUIT command
4793 * };
4794 */
4795
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004796 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4797 * const char mysql41_client_auth_pkt[] = {
4798 * "\x0e\x00\x00\" // packet length
4799 * "\x01" // packet number
4800 * "\x00\x00\x00\x00" // client capabilities
4801 * "\x00\x00\x00\x01" // max packet
4802 * "\x21" // character set (UTF-8)
4803 * char[23] // All zeroes
4804 * "haproxy\x00" // username (null terminated string)
4805 * "\x00" // filler (always 0x00)
4806 * "\x01\x00\x00" // packet length
4807 * "\x00" // packet number
4808 * "\x01" // COM_QUIT command
4809 * };
4810 */
4811
4812
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004813 if (*(args[2])) {
4814 int cur_arg = 2;
4815
4816 while (*(args[cur_arg])) {
4817 if (strcmp(args[cur_arg], "user") == 0) {
4818 char *mysqluser;
4819 int packetlen, reqlen, userlen;
4820
4821 /* suboption header - needs additional argument for it */
4822 if (*(args[cur_arg+1]) == 0) {
4823 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4824 file, linenum, args[0], args[1], args[cur_arg]);
4825 err_code |= ERR_ALERT | ERR_FATAL;
4826 goto out;
4827 }
4828 mysqluser = args[cur_arg + 1];
4829 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004830
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004831 if (*(args[cur_arg+2])) {
4832 if (!strcmp(args[cur_arg+2], "post-41")) {
4833 packetlen = userlen + 7 + 27;
4834 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004835
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004836 free(curproxy->check_req);
4837 curproxy->check_req = (char *)calloc(1, reqlen);
4838 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004839
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004840 snprintf(curproxy->check_req, 4, "%c%c%c",
4841 ((unsigned char) packetlen & 0xff),
4842 ((unsigned char) (packetlen >> 8) & 0xff),
4843 ((unsigned char) (packetlen >> 16) & 0xff));
4844
4845 curproxy->check_req[3] = 1;
4846 curproxy->check_req[5] = 130;
4847 curproxy->check_req[11] = 1;
4848 curproxy->check_req[12] = 33;
4849 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4850 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4851 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4852 cur_arg += 3;
4853 } else {
4854 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4855 err_code |= ERR_ALERT | ERR_FATAL;
4856 goto out;
4857 }
4858 } else {
4859 packetlen = userlen + 7;
4860 reqlen = packetlen + 9;
4861
4862 free(curproxy->check_req);
4863 curproxy->check_req = (char *)calloc(1, reqlen);
4864 curproxy->check_len = reqlen;
4865
4866 snprintf(curproxy->check_req, 4, "%c%c%c",
4867 ((unsigned char) packetlen & 0xff),
4868 ((unsigned char) (packetlen >> 8) & 0xff),
4869 ((unsigned char) (packetlen >> 16) & 0xff));
4870
4871 curproxy->check_req[3] = 1;
4872 curproxy->check_req[5] = 128;
4873 curproxy->check_req[8] = 1;
4874 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4875 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4876 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4877 cur_arg += 2;
4878 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004879 } else {
4880 /* unknown suboption - catchall */
4881 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4882 file, linenum, args[0], args[1]);
4883 err_code |= ERR_ALERT | ERR_FATAL;
4884 goto out;
4885 }
4886 } /* end while loop */
4887 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004888 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004889 else if (!strcmp(args[1], "ldap-check")) {
4890 /* use LDAP request to check servers' health */
4891 free(curproxy->check_req);
4892 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004893 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004894 curproxy->options2 |= PR_O2_LDAP_CHK;
4895
4896 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
4897 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
4898 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004899 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4900 goto out;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004901 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004902 else if (!strcmp(args[1], "tcp-check")) {
4903 /* use raw TCPCHK send/expect to check servers' health */
4904 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4905 err_code |= ERR_WARN;
4906
4907 free(curproxy->check_req);
4908 curproxy->check_req = NULL;
4909 curproxy->options2 &= ~PR_O2_CHK_ANY;
4910 curproxy->options2 |= PR_O2_TCPCHK_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004911 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4912 goto out;
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004913 }
Simon Horman98637e52014-06-20 12:30:16 +09004914 else if (!strcmp(args[1], "external-check")) {
4915 /* excute an external command to check servers' health */
4916 free(curproxy->check_req);
4917 curproxy->check_req = NULL;
4918 curproxy->options2 &= ~PR_O2_CHK_ANY;
4919 curproxy->options2 |= PR_O2_EXT_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004920 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4921 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09004922 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004923 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004924 int cur_arg;
4925
4926 /* insert x-forwarded-for field, but not for the IP address listed as an except.
4927 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004928 */
Ross Westaf72a1d2008-08-03 10:51:45 +02004929
Willy Tarreau87cf5142011-08-19 22:57:24 +02004930 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02004931
4932 free(curproxy->fwdfor_hdr_name);
4933 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
4934 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
4935
4936 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
4937 cur_arg = 2;
4938 while (*(args[cur_arg])) {
4939 if (!strcmp(args[cur_arg], "except")) {
4940 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004941 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004942 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4943 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004944 err_code |= ERR_ALERT | ERR_FATAL;
4945 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004946 }
4947 /* flush useless bits */
4948 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02004949 cur_arg += 2;
4950 } else if (!strcmp(args[cur_arg], "header")) {
4951 /* suboption header - needs additional argument for it */
4952 if (*(args[cur_arg+1]) == 0) {
4953 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4954 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004955 err_code |= ERR_ALERT | ERR_FATAL;
4956 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02004957 }
4958 free(curproxy->fwdfor_hdr_name);
4959 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
4960 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
4961 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02004962 } else if (!strcmp(args[cur_arg], "if-none")) {
4963 curproxy->options &= ~PR_O_FF_ALWAYS;
4964 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004965 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02004966 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02004967 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02004968 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004969 err_code |= ERR_ALERT | ERR_FATAL;
4970 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004971 }
Ross Westaf72a1d2008-08-03 10:51:45 +02004972 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004973 }
Maik Broemme2850cb42009-04-17 18:53:21 +02004974 else if (!strcmp(args[1], "originalto")) {
4975 int cur_arg;
4976
4977 /* insert x-original-to field, but not for the IP address listed as an except.
4978 * set default options (ie: bitfield, header name, etc)
4979 */
4980
4981 curproxy->options |= PR_O_ORGTO;
4982
4983 free(curproxy->orgto_hdr_name);
4984 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
4985 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
4986
Willy Tarreau87cf5142011-08-19 22:57:24 +02004987 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02004988 cur_arg = 2;
4989 while (*(args[cur_arg])) {
4990 if (!strcmp(args[cur_arg], "except")) {
4991 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004992 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 +02004993 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4994 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004995 err_code |= ERR_ALERT | ERR_FATAL;
4996 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004997 }
4998 /* flush useless bits */
4999 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
5000 cur_arg += 2;
5001 } else if (!strcmp(args[cur_arg], "header")) {
5002 /* suboption header - needs additional argument for it */
5003 if (*(args[cur_arg+1]) == 0) {
5004 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5005 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005006 err_code |= ERR_ALERT | ERR_FATAL;
5007 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005008 }
5009 free(curproxy->orgto_hdr_name);
5010 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
5011 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
5012 cur_arg += 2;
5013 } else {
5014 /* unknown suboption - catchall */
5015 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
5016 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005017 err_code |= ERR_ALERT | ERR_FATAL;
5018 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005019 }
5020 } /* end while loop */
5021 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005022 else {
5023 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005024 err_code |= ERR_ALERT | ERR_FATAL;
5025 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005026 }
Willy Tarreau93893792009-07-23 13:19:11 +02005027 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005028 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005029 else if (!strcmp(args[0], "default_backend")) {
5030 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005031 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005032
5033 if (*(args[1]) == 0) {
5034 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005035 err_code |= ERR_ALERT | ERR_FATAL;
5036 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005037 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005038 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005039 curproxy->defbe.name = strdup(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005040
5041 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5042 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005043 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005044 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01005045 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005046 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005047
Willy Tarreaua3c504c2014-04-28 22:37:32 +02005048 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
5049 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 +01005050 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005051 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005052 /* enable reconnections to dispatch */
5053 curproxy->options |= PR_O_REDISP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005054
5055 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5056 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005057 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005058 else if (!strcmp(args[0], "http-reuse")) {
5059 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5060 err_code |= ERR_WARN;
5061
5062 if (strcmp(args[1], "never") == 0) {
5063 /* enable a graceful server shutdown on an HTTP 404 response */
5064 curproxy->options &= ~PR_O_REUSE_MASK;
5065 curproxy->options |= PR_O_REUSE_NEVR;
5066 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5067 goto out;
5068 }
Willy Tarreau161d45f2015-08-05 16:02:46 +02005069 else if (strcmp(args[1], "safe") == 0) {
5070 /* enable a graceful server shutdown on an HTTP 404 response */
5071 curproxy->options &= ~PR_O_REUSE_MASK;
5072 curproxy->options |= PR_O_REUSE_SAFE;
5073 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5074 goto out;
5075 }
Willy Tarreau449d74a2015-08-05 17:16:33 +02005076 else if (strcmp(args[1], "aggressive") == 0) {
5077 curproxy->options &= ~PR_O_REUSE_MASK;
5078 curproxy->options |= PR_O_REUSE_AGGR;
5079 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5080 goto out;
5081 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005082 else if (strcmp(args[1], "always") == 0) {
5083 /* enable a graceful server shutdown on an HTTP 404 response */
5084 curproxy->options &= ~PR_O_REUSE_MASK;
5085 curproxy->options |= PR_O_REUSE_ALWS;
5086 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5087 goto out;
5088 }
5089 else {
Willy Tarreau449d74a2015-08-05 17:16:33 +02005090 Alert("parsing [%s:%d] : '%s' only supports 'never', 'safe', 'aggressive', 'always'.\n", file, linenum, args[0]);
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005091 err_code |= ERR_ALERT | ERR_FATAL;
5092 goto out;
5093 }
5094 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005095 else if (!strcmp(args[0], "http-check")) {
5096 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005097 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01005098
5099 if (strcmp(args[1], "disable-on-404") == 0) {
5100 /* enable a graceful server shutdown on an HTTP 404 response */
5101 curproxy->options |= PR_O_DISABLE404;
William Lallemanddf1425a2015-04-28 20:17:49 +02005102 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5103 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005104 }
Willy Tarreauef781042010-01-27 11:53:01 +01005105 else if (strcmp(args[1], "send-state") == 0) {
5106 /* enable emission of the apparent state of a server in HTTP checks */
5107 curproxy->options2 |= PR_O2_CHK_SNDST;
William Lallemanddf1425a2015-04-28 20:17:49 +02005108 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5109 goto out;
Willy Tarreauef781042010-01-27 11:53:01 +01005110 }
Willy Tarreaubd741542010-03-16 18:46:54 +01005111 else if (strcmp(args[1], "expect") == 0) {
5112 const char *ptr_arg;
5113 int cur_arg;
5114
5115 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5116 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5117 err_code |= ERR_ALERT | ERR_FATAL;
5118 goto out;
5119 }
5120
5121 cur_arg = 2;
5122 /* consider exclamation marks, sole or at the beginning of a word */
5123 while (*(ptr_arg = args[cur_arg])) {
5124 while (*ptr_arg == '!') {
5125 curproxy->options2 ^= PR_O2_EXP_INV;
5126 ptr_arg++;
5127 }
5128 if (*ptr_arg)
5129 break;
5130 cur_arg++;
5131 }
5132 /* now ptr_arg points to the beginning of a word past any possible
5133 * exclamation mark, and cur_arg is the argument which holds this word.
5134 */
5135 if (strcmp(ptr_arg, "status") == 0) {
5136 if (!*(args[cur_arg + 1])) {
5137 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5138 file, linenum, args[0], args[1], ptr_arg);
5139 err_code |= ERR_ALERT | ERR_FATAL;
5140 goto out;
5141 }
5142 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005143 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005144 curproxy->expect_str = strdup(args[cur_arg + 1]);
5145 }
5146 else if (strcmp(ptr_arg, "string") == 0) {
5147 if (!*(args[cur_arg + 1])) {
5148 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5149 file, linenum, args[0], args[1], ptr_arg);
5150 err_code |= ERR_ALERT | ERR_FATAL;
5151 goto out;
5152 }
5153 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005154 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005155 curproxy->expect_str = strdup(args[cur_arg + 1]);
5156 }
5157 else if (strcmp(ptr_arg, "rstatus") == 0) {
5158 if (!*(args[cur_arg + 1])) {
5159 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5160 file, linenum, args[0], args[1], ptr_arg);
5161 err_code |= ERR_ALERT | ERR_FATAL;
5162 goto out;
5163 }
5164 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005165 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005166 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005167 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005168 free(curproxy->expect_regex);
5169 curproxy->expect_regex = NULL;
5170 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005171 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005172 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5173 error = NULL;
5174 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5175 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5176 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5177 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005178 err_code |= ERR_ALERT | ERR_FATAL;
5179 goto out;
5180 }
5181 }
5182 else if (strcmp(ptr_arg, "rstring") == 0) {
5183 if (!*(args[cur_arg + 1])) {
5184 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5185 file, linenum, args[0], args[1], ptr_arg);
5186 err_code |= ERR_ALERT | ERR_FATAL;
5187 goto out;
5188 }
5189 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005190 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005191 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005192 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005193 free(curproxy->expect_regex);
5194 curproxy->expect_regex = NULL;
5195 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005196 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005197 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5198 error = NULL;
5199 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5200 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5201 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5202 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005203 err_code |= ERR_ALERT | ERR_FATAL;
5204 goto out;
5205 }
5206 }
5207 else {
5208 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
5209 file, linenum, args[0], args[1], ptr_arg);
5210 err_code |= ERR_ALERT | ERR_FATAL;
5211 goto out;
5212 }
5213 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005214 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005215 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 +02005216 err_code |= ERR_ALERT | ERR_FATAL;
5217 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005218 }
5219 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005220 else if (!strcmp(args[0], "tcp-check")) {
5221 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5222 err_code |= ERR_WARN;
5223
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005224 if (strcmp(args[1], "comment") == 0) {
5225 int cur_arg;
5226 struct tcpcheck_rule *tcpcheck;
5227
5228 cur_arg = 1;
5229 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5230 tcpcheck->action = TCPCHK_ACT_COMMENT;
5231
5232 if (!*args[cur_arg + 1]) {
5233 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5234 file, linenum, args[cur_arg]);
5235 err_code |= ERR_ALERT | ERR_FATAL;
5236 goto out;
5237 }
5238
5239 tcpcheck->comment = strdup(args[cur_arg + 1]);
5240
5241 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
William Lallemanddf1425a2015-04-28 20:17:49 +02005242 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
5243 goto out;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005244 }
5245 else if (strcmp(args[1], "connect") == 0) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005246 const char *ptr_arg;
5247 int cur_arg;
5248 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005249
5250 /* check if first rule is also a 'connect' action */
Willy Tarreau5581c272015-05-13 12:24:53 +02005251 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
5252 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
5253 tcpcheck->action == TCPCHK_ACT_COMMENT) {
5254 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
5255 }
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005256
Willy Tarreau5581c272015-05-13 12:24:53 +02005257 if (&tcpcheck->list != &curproxy->tcpcheck_rules
5258 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
5259 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
5260 file, linenum);
5261 err_code |= ERR_ALERT | ERR_FATAL;
5262 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005263 }
5264
5265 cur_arg = 2;
5266 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5267 tcpcheck->action = TCPCHK_ACT_CONNECT;
5268
5269 /* parsing each parameters to fill up the rule */
5270 while (*(ptr_arg = args[cur_arg])) {
5271 /* tcp port */
5272 if (strcmp(args[cur_arg], "port") == 0) {
5273 if ( (atol(args[cur_arg + 1]) > 65535) ||
5274 (atol(args[cur_arg + 1]) < 1) ){
5275 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
5276 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
5277 err_code |= ERR_ALERT | ERR_FATAL;
5278 goto out;
5279 }
5280 tcpcheck->port = atol(args[cur_arg + 1]);
5281 cur_arg += 2;
5282 }
5283 /* send proxy protocol */
5284 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
5285 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
5286 cur_arg++;
5287 }
5288#ifdef USE_OPENSSL
5289 else if (strcmp(args[cur_arg], "ssl") == 0) {
5290 curproxy->options |= PR_O_TCPCHK_SSL;
5291 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
5292 cur_arg++;
5293 }
5294#endif /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005295 /* comment for this tcpcheck line */
5296 else if (strcmp(args[cur_arg], "comment") == 0) {
5297 if (!*args[cur_arg + 1]) {
5298 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5299 file, linenum, args[cur_arg]);
5300 err_code |= ERR_ALERT | ERR_FATAL;
5301 goto out;
5302 }
5303 tcpcheck->comment = strdup(args[cur_arg + 1]);
5304 cur_arg += 2;
5305 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005306 else {
5307#ifdef USE_OPENSSL
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005308 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 +01005309#else /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005310 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 +01005311#endif /* USE_OPENSSL */
5312 file, linenum, args[0], args[1], args[cur_arg]);
5313 err_code |= ERR_ALERT | ERR_FATAL;
5314 goto out;
5315 }
5316
5317 }
5318
5319 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5320 }
5321 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005322 if (! *(args[2]) ) {
5323 /* SEND string expected */
5324 Alert("parsing [%s:%d] : '%s %s %s' expects <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
5331 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5332
5333 tcpcheck->action = TCPCHK_ACT_SEND;
5334 tcpcheck->string_len = strlen(args[2]);
5335 tcpcheck->string = strdup(args[2]);
5336 tcpcheck->expect_regex = NULL;
5337
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005338 /* comment for this tcpcheck line */
5339 if (strcmp(args[3], "comment") == 0) {
5340 if (!*args[4]) {
5341 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5342 file, linenum, args[3]);
5343 err_code |= ERR_ALERT | ERR_FATAL;
5344 goto out;
5345 }
5346 tcpcheck->comment = strdup(args[4]);
5347 }
5348
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005349 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5350 }
5351 }
5352 else if (strcmp(args[1], "send-binary") == 0) {
5353 if (! *(args[2]) ) {
5354 /* SEND binary string expected */
5355 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
5356 file, linenum, args[0], args[1], args[2]);
5357 err_code |= ERR_ALERT | ERR_FATAL;
5358 goto out;
5359 } else {
5360 struct tcpcheck_rule *tcpcheck;
5361 char *err = NULL;
5362
5363 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5364
5365 tcpcheck->action = TCPCHK_ACT_SEND;
5366 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5367 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5368 file, linenum, args[0], args[1], args[2], err);
5369 err_code |= ERR_ALERT | ERR_FATAL;
5370 goto out;
5371 }
5372 tcpcheck->expect_regex = NULL;
5373
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005374 /* comment for this tcpcheck line */
5375 if (strcmp(args[3], "comment") == 0) {
5376 if (!*args[4]) {
5377 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5378 file, linenum, args[3]);
5379 err_code |= ERR_ALERT | ERR_FATAL;
5380 goto out;
5381 }
5382 tcpcheck->comment = strdup(args[4]);
5383 }
5384
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005385 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5386 }
5387 }
5388 else if (strcmp(args[1], "expect") == 0) {
5389 const char *ptr_arg;
5390 int cur_arg;
5391 int inverse = 0;
5392
5393 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5394 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5395 err_code |= ERR_ALERT | ERR_FATAL;
5396 goto out;
5397 }
5398
5399 cur_arg = 2;
5400 /* consider exclamation marks, sole or at the beginning of a word */
5401 while (*(ptr_arg = args[cur_arg])) {
5402 while (*ptr_arg == '!') {
5403 inverse = !inverse;
5404 ptr_arg++;
5405 }
5406 if (*ptr_arg)
5407 break;
5408 cur_arg++;
5409 }
5410 /* now ptr_arg points to the beginning of a word past any possible
5411 * exclamation mark, and cur_arg is the argument which holds this word.
5412 */
5413 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005414 struct tcpcheck_rule *tcpcheck;
5415 char *err = NULL;
5416
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005417 if (!*(args[cur_arg + 1])) {
5418 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
5419 file, linenum, args[0], args[1], ptr_arg);
5420 err_code |= ERR_ALERT | ERR_FATAL;
5421 goto out;
5422 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005423
5424 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5425
5426 tcpcheck->action = TCPCHK_ACT_EXPECT;
5427 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5428 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5429 file, linenum, args[0], args[1], args[2], err);
5430 err_code |= ERR_ALERT | ERR_FATAL;
5431 goto out;
5432 }
5433 tcpcheck->expect_regex = NULL;
5434 tcpcheck->inverse = inverse;
5435
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005436 /* tcpcheck comment */
5437 cur_arg += 2;
5438 if (strcmp(args[cur_arg], "comment") == 0) {
5439 if (!*args[cur_arg + 1]) {
5440 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5441 file, linenum, args[cur_arg + 1]);
5442 err_code |= ERR_ALERT | ERR_FATAL;
5443 goto out;
5444 }
5445 tcpcheck->comment = strdup(args[cur_arg + 1]);
5446 }
5447
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005448 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5449 }
5450 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005451 struct tcpcheck_rule *tcpcheck;
5452
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005453 if (!*(args[cur_arg + 1])) {
5454 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5455 file, linenum, args[0], args[1], ptr_arg);
5456 err_code |= ERR_ALERT | ERR_FATAL;
5457 goto out;
5458 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005459
5460 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5461
5462 tcpcheck->action = TCPCHK_ACT_EXPECT;
5463 tcpcheck->string_len = strlen(args[cur_arg + 1]);
5464 tcpcheck->string = strdup(args[cur_arg + 1]);
5465 tcpcheck->expect_regex = NULL;
5466 tcpcheck->inverse = inverse;
5467
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005468 /* tcpcheck comment */
5469 cur_arg += 2;
5470 if (strcmp(args[cur_arg], "comment") == 0) {
5471 if (!*args[cur_arg + 1]) {
5472 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5473 file, linenum, args[cur_arg + 1]);
5474 err_code |= ERR_ALERT | ERR_FATAL;
5475 goto out;
5476 }
5477 tcpcheck->comment = strdup(args[cur_arg + 1]);
5478 }
5479
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005480 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5481 }
5482 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005483 struct tcpcheck_rule *tcpcheck;
5484
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005485 if (!*(args[cur_arg + 1])) {
5486 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5487 file, linenum, args[0], args[1], ptr_arg);
5488 err_code |= ERR_ALERT | ERR_FATAL;
5489 goto out;
5490 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005491
5492 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5493
5494 tcpcheck->action = TCPCHK_ACT_EXPECT;
5495 tcpcheck->string_len = 0;
5496 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005497 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
5498 error = NULL;
5499 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
5500 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5501 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5502 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005503 err_code |= ERR_ALERT | ERR_FATAL;
5504 goto out;
5505 }
5506 tcpcheck->inverse = inverse;
5507
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005508 /* tcpcheck comment */
5509 cur_arg += 2;
5510 if (strcmp(args[cur_arg], "comment") == 0) {
5511 if (!*args[cur_arg + 1]) {
5512 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5513 file, linenum, args[cur_arg + 1]);
5514 err_code |= ERR_ALERT | ERR_FATAL;
5515 goto out;
5516 }
5517 tcpcheck->comment = strdup(args[cur_arg + 1]);
5518 }
5519
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005520 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5521 }
5522 else {
5523 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
5524 file, linenum, args[0], args[1], ptr_arg);
5525 err_code |= ERR_ALERT | ERR_FATAL;
5526 goto out;
5527 }
5528 }
5529 else {
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005530 Alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005531 err_code |= ERR_ALERT | ERR_FATAL;
5532 goto out;
5533 }
5534 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01005535 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02005536 if (curproxy == &defproxy) {
5537 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005538 err_code |= ERR_ALERT | ERR_FATAL;
5539 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02005540 }
5541
Willy Tarreaub80c2302007-11-30 20:51:32 +01005542 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005543 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005544
5545 if (strcmp(args[1], "fail") == 0) {
5546 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01005547 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01005548 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
5549 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005550 err_code |= ERR_ALERT | ERR_FATAL;
5551 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005552 }
5553
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005554 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
5555 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
5556 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005557 err_code |= ERR_ALERT | ERR_FATAL;
5558 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005559 }
5560 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
5561 }
5562 else {
5563 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005564 err_code |= ERR_ALERT | ERR_FATAL;
5565 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005566 }
5567 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005568#ifdef TPROXY
5569 else if (!strcmp(args[0], "transparent")) {
5570 /* enable transparent proxy connections */
5571 curproxy->options |= PR_O_TRANSP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005572 if (alertif_too_many_args(0, file, linenum, args, &err_code))
5573 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005574 }
5575#endif
5576 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005577 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005578 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005579
Willy Tarreaubaaee002006-06-26 02:48:02 +02005580 if (*(args[1]) == 0) {
5581 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005582 err_code |= ERR_ALERT | ERR_FATAL;
5583 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005584 }
5585 curproxy->maxconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005586 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5587 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005588 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005589 else if (!strcmp(args[0], "backlog")) { /* backlog */
5590 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005591 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005592
5593 if (*(args[1]) == 0) {
5594 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005595 err_code |= ERR_ALERT | ERR_FATAL;
5596 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005597 }
5598 curproxy->backlog = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005599 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5600 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005601 }
Willy Tarreau86034312006-12-29 00:10:33 +01005602 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005603 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005604 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005605
Willy Tarreau86034312006-12-29 00:10:33 +01005606 if (*(args[1]) == 0) {
5607 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005608 err_code |= ERR_ALERT | ERR_FATAL;
5609 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005610 }
5611 curproxy->fullconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005612 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5613 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005614 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005615 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
5616 if (*(args[1]) == 0) {
5617 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005618 err_code |= ERR_ALERT | ERR_FATAL;
5619 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005620 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005621 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
5622 if (err) {
5623 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
5624 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02005625 err_code |= ERR_ALERT | ERR_FATAL;
5626 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005627 }
5628 curproxy->grace = val;
William Lallemanddf1425a2015-04-28 20:17:49 +02005629 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5630 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005631 }
5632 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01005633 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005634 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005635 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005636
Willy Tarreaubaaee002006-06-26 02:48:02 +02005637 if (curproxy == &defproxy) {
5638 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005639 err_code |= ERR_ALERT | ERR_FATAL;
5640 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005641 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005642 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005643 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005644
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02005645 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005646 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005647 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005648 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005649 goto out;
5650 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005651
5652 proto = protocol_by_family(sk->ss_family);
5653 if (!proto || !proto->connect) {
5654 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5655 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005656 err_code |= ERR_ALERT | ERR_FATAL;
5657 goto out;
5658 }
5659
5660 if (port1 != port2) {
5661 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5662 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005663 err_code |= ERR_ALERT | ERR_FATAL;
5664 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005665 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005666
5667 if (!port1) {
5668 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5669 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005670 err_code |= ERR_ALERT | ERR_FATAL;
5671 goto out;
5672 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005673
William Lallemanddf1425a2015-04-28 20:17:49 +02005674 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5675 goto out;
5676
Willy Tarreaud5191e72010-02-09 20:50:45 +01005677 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005678 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005679 }
5680 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005681 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005682 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005683
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005684 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5685 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005686 err_code |= ERR_ALERT | ERR_FATAL;
5687 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005688 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005689 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005690 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005691 /**
5692 * The syntax for hash-type config element is
5693 * hash-type {map-based|consistent} [[<algo>] avalanche]
5694 *
5695 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5696 */
5697 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005698
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005699 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5700 err_code |= ERR_WARN;
5701
5702 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005703 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5704 }
5705 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005706 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5707 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005708 else if (strcmp(args[1], "avalanche") == 0) {
5709 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]);
5710 err_code |= ERR_ALERT | ERR_FATAL;
5711 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005712 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005713 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005714 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005715 err_code |= ERR_ALERT | ERR_FATAL;
5716 goto out;
5717 }
Bhaskar98634f02013-10-29 23:30:51 -04005718
5719 /* set the hash function to use */
5720 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005721 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005722 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005723
5724 /* if consistent with no argument, then avalanche modifier is also applied */
5725 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5726 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005727 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005728 /* set the hash function */
5729 if (!strcmp(args[2], "sdbm")) {
5730 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5731 }
5732 else if (!strcmp(args[2], "djb2")) {
5733 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005734 }
5735 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005736 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005737 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005738 else if (!strcmp(args[2], "crc32")) {
5739 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5740 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005741 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005742 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 -05005743 err_code |= ERR_ALERT | ERR_FATAL;
5744 goto out;
5745 }
5746
5747 /* set the hash modifier */
5748 if (!strcmp(args[3], "avalanche")) {
5749 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5750 }
5751 else if (*args[3]) {
5752 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5753 err_code |= ERR_ALERT | ERR_FATAL;
5754 goto out;
5755 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005756 }
William Lallemanda73203e2012-03-12 12:48:57 +01005757 }
William Lallemanda73203e2012-03-12 12:48:57 +01005758 else if (strcmp(args[0], "unique-id-format") == 0) {
5759 if (!*(args[1])) {
5760 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5761 err_code |= ERR_ALERT | ERR_FATAL;
5762 goto out;
5763 }
William Lallemand3203ff42012-11-11 17:30:56 +01005764 if (*(args[2])) {
5765 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5766 err_code |= ERR_ALERT | ERR_FATAL;
5767 goto out;
5768 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005769 free(curproxy->conf.uniqueid_format_string);
5770 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005771
Willy Tarreau62a61232013-04-12 18:13:46 +02005772 free(curproxy->conf.uif_file);
5773 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5774 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005775 }
William Lallemanda73203e2012-03-12 12:48:57 +01005776
5777 else if (strcmp(args[0], "unique-id-header") == 0) {
5778 if (!*(args[1])) {
5779 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5780 err_code |= ERR_ALERT | ERR_FATAL;
5781 goto out;
5782 }
5783 free(curproxy->header_unique_id);
5784 curproxy->header_unique_id = strdup(args[1]);
5785 }
5786
William Lallemand723b73a2012-02-08 16:37:49 +01005787 else if (strcmp(args[0], "log-format") == 0) {
5788 if (!*(args[1])) {
5789 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5790 err_code |= ERR_ALERT | ERR_FATAL;
5791 goto out;
5792 }
William Lallemand3203ff42012-11-11 17:30:56 +01005793 if (*(args[2])) {
5794 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5795 err_code |= ERR_ALERT | ERR_FATAL;
5796 goto out;
5797 }
Willy Tarreau196729e2012-05-31 19:30:26 +02005798
Willy Tarreau62a61232013-04-12 18:13:46 +02005799 if (curproxy->conf.logformat_string != default_http_log_format &&
5800 curproxy->conf.logformat_string != default_tcp_log_format &&
5801 curproxy->conf.logformat_string != clf_http_log_format)
5802 free(curproxy->conf.logformat_string);
5803 curproxy->conf.logformat_string = strdup(args[1]);
5804
5805 free(curproxy->conf.lfs_file);
5806 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5807 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005808
5809 /* get a chance to improve log-format error reporting by
5810 * reporting the correct line-number when possible.
5811 */
5812 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5813 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5814 file, linenum, curproxy->id);
5815 err_code |= ERR_WARN;
5816 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005817 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02005818 else if (!strcmp(args[0], "log-format-sd")) {
5819 if (!*(args[1])) {
5820 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5821 err_code |= ERR_ALERT | ERR_FATAL;
5822 goto out;
5823 }
5824 if (*(args[2])) {
5825 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5826 err_code |= ERR_ALERT | ERR_FATAL;
5827 goto out;
5828 }
5829
5830 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
5831 free(curproxy->conf.logformat_sd_string);
5832 curproxy->conf.logformat_sd_string = strdup(args[1]);
5833
5834 free(curproxy->conf.lfsd_file);
5835 curproxy->conf.lfsd_file = strdup(curproxy->conf.args.file);
5836 curproxy->conf.lfsd_line = curproxy->conf.args.line;
5837
5838 /* get a chance to improve log-format-sd error reporting by
5839 * reporting the correct line-number when possible.
5840 */
5841 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5842 Warning("parsing [%s:%d] : backend '%s' : 'log-format-sd' directive is ignored in backends.\n",
5843 file, linenum, curproxy->id);
5844 err_code |= ERR_WARN;
5845 }
5846 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01005847 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
5848 if (*(args[1]) == 0) {
5849 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
5850 err_code |= ERR_ALERT | ERR_FATAL;
5851 goto out;
5852 }
Dragan Dosen43885c72015-10-01 13:18:13 +02005853 chunk_destroy(&curproxy->log_tag);
5854 chunk_initstr(&curproxy->log_tag, strdup(args[1]));
Willy Tarreau094af4e2015-01-07 15:03:42 +01005855 }
William Lallemand0f99e342011-10-12 17:50:54 +02005856 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
5857 /* delete previous herited or defined syslog servers */
5858 struct logsrv *back;
5859
5860 if (*(args[1]) != 0) {
5861 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
5862 err_code |= ERR_ALERT | ERR_FATAL;
5863 goto out;
5864 }
5865
William Lallemand723b73a2012-02-08 16:37:49 +01005866 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
5867 LIST_DEL(&tmplogsrv->list);
5868 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02005869 }
5870 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005871 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02005872 struct logsrv *logsrv;
5873
Willy Tarreaubaaee002006-06-26 02:48:02 +02005874 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005875 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01005876 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02005877 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01005878 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02005879 LIST_INIT(&node->list);
5880 LIST_ADDQ(&curproxy->logsrvs, &node->list);
5881 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005882 }
5883 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005884 struct sockaddr_storage *sk;
5885 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02005886 int arg = 0;
5887 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02005888
5889 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005890
Willy Tarreau18324f52014-06-27 18:10:07 +02005891 /* just after the address, a length may be specified */
5892 if (strcmp(args[arg+2], "len") == 0) {
5893 len = atoi(args[arg+3]);
5894 if (len < 80 || len > 65535) {
5895 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
5896 file, linenum, args[arg+3]);
5897 err_code |= ERR_ALERT | ERR_FATAL;
5898 goto out;
5899 }
5900 logsrv->maxlen = len;
5901
5902 /* skip these two args */
5903 arg += 2;
5904 }
5905 else
5906 logsrv->maxlen = MAX_SYSLOG_LEN;
5907
5908 if (logsrv->maxlen > global.max_syslog_len) {
5909 global.max_syslog_len = logsrv->maxlen;
Dragan Dosen59cee972015-09-19 22:09:02 +02005910 logheader = realloc(logheader, global.max_syslog_len + 1);
Dragan Dosen1322d092015-09-22 16:05:32 +02005911 logheader_rfc5424 = realloc(logheader_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02005912 logline = realloc(logline, global.max_syslog_len + 1);
Dragan Dosen0b85ece2015-09-25 19:17:44 +02005913 logline_rfc5424 = realloc(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02005914 }
5915
Dragan Dosen1322d092015-09-22 16:05:32 +02005916 /* after the length, a format may be specified */
5917 if (strcmp(args[arg+2], "format") == 0) {
5918 logsrv->format = get_log_format(args[arg+3]);
5919 if (logsrv->format < 0) {
5920 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
5921 err_code |= ERR_ALERT | ERR_FATAL;
5922 goto out;
5923 }
5924
5925 /* skip these two args */
5926 arg += 2;
5927 }
5928
William Lallemanddf1425a2015-04-28 20:17:49 +02005929 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
5930 goto out;
5931
Willy Tarreau18324f52014-06-27 18:10:07 +02005932 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005933 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005934 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005935 err_code |= ERR_ALERT | ERR_FATAL;
5936 goto out;
5937
Willy Tarreaubaaee002006-06-26 02:48:02 +02005938 }
5939
William Lallemand0f99e342011-10-12 17:50:54 +02005940 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02005941 if (*(args[arg+3])) {
5942 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005943 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005944 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005945 err_code |= ERR_ALERT | ERR_FATAL;
5946 goto out;
5947
Willy Tarreaubaaee002006-06-26 02:48:02 +02005948 }
5949 }
5950
William Lallemand0f99e342011-10-12 17:50:54 +02005951 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02005952 if (*(args[arg+4])) {
5953 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01005954 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005955 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02005956 err_code |= ERR_ALERT | ERR_FATAL;
5957 goto out;
5958
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005959 }
5960 }
5961
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02005962 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005963 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005964 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005965 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005966 goto out;
5967 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005968
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005969 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005970
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005971 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005972 if (port1 != port2) {
5973 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5974 file, linenum, args[0], args[1]);
5975 err_code |= ERR_ALERT | ERR_FATAL;
5976 goto out;
5977 }
5978
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005979 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02005980 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005981 }
William Lallemand0f99e342011-10-12 17:50:54 +02005982
5983 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005984 }
5985 else {
5986 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
5987 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005988 err_code |= ERR_ALERT | ERR_FATAL;
5989 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005990 }
5991 }
5992 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005993 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005994 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01005995 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005996 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005997
Willy Tarreau977b8e42006-12-29 14:19:17 +01005998 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005999 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006000
Willy Tarreaubaaee002006-06-26 02:48:02 +02006001 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006002 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
6003 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02006004 err_code |= ERR_ALERT | ERR_FATAL;
6005 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006006 }
Willy Tarreau368480c2009-03-01 08:27:21 +01006007
6008 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01006009 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6010 free(curproxy->conn_src.iface_name);
6011 curproxy->conn_src.iface_name = NULL;
6012 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01006013
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006014 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006015 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006016 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006017 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006018 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006019 goto out;
6020 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006021
6022 proto = protocol_by_family(sk->ss_family);
6023 if (!proto || !proto->connect) {
6024 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006025 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006026 err_code |= ERR_ALERT | ERR_FATAL;
6027 goto out;
6028 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006029
6030 if (port1 != port2) {
6031 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6032 file, linenum, args[0], args[1]);
6033 err_code |= ERR_ALERT | ERR_FATAL;
6034 goto out;
6035 }
6036
Willy Tarreauef9a3602012-12-08 22:29:20 +01006037 curproxy->conn_src.source_addr = *sk;
6038 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006039
6040 cur_arg = 2;
6041 while (*(args[cur_arg])) {
6042 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau29fbe512015-08-20 19:35:14 +02006043#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006044 if (!*args[cur_arg + 1]) {
6045 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
6046 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006047 err_code |= ERR_ALERT | ERR_FATAL;
6048 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006049 }
6050
6051 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006052 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6053 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006054 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006055 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6056 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02006057 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
6058 char *name, *end;
6059
6060 name = args[cur_arg+1] + 7;
6061 while (isspace(*name))
6062 name++;
6063
6064 end = name;
6065 while (*end && !isspace(*end) && *end != ',' && *end != ')')
6066 end++;
6067
Willy Tarreauef9a3602012-12-08 22:29:20 +01006068 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6069 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
6070 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
6071 curproxy->conn_src.bind_hdr_len = end - name;
6072 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
6073 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
6074 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02006075
6076 /* now look for an occurrence number */
6077 while (isspace(*end))
6078 end++;
6079 if (*end == ',') {
6080 end++;
6081 name = end;
6082 if (*end == '-')
6083 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01006084 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02006085 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01006086 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006087 }
6088
Willy Tarreauef9a3602012-12-08 22:29:20 +01006089 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02006090 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
6091 " occurrences values smaller than %d.\n",
6092 file, linenum, MAX_HDR_HISTORY);
6093 err_code |= ERR_ALERT | ERR_FATAL;
6094 goto out;
6095 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006096 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01006097 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006098
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006099 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006100 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006101 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006102 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006103 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006104 goto out;
6105 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006106
6107 proto = protocol_by_family(sk->ss_family);
6108 if (!proto || !proto->connect) {
6109 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
6110 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006111 err_code |= ERR_ALERT | ERR_FATAL;
6112 goto out;
6113 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006114
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006115 if (port1 != port2) {
6116 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6117 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006118 err_code |= ERR_ALERT | ERR_FATAL;
6119 goto out;
6120 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006121 curproxy->conn_src.tproxy_addr = *sk;
6122 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006123 }
6124 global.last_checks |= LSTCHK_NETADM;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006125#else /* no TPROXY support */
6126 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01006127 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006128 err_code |= ERR_ALERT | ERR_FATAL;
6129 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006130#endif
6131 cur_arg += 2;
6132 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01006133 }
6134
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006135 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
6136#ifdef SO_BINDTODEVICE
6137 if (!*args[cur_arg + 1]) {
6138 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
6139 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006140 err_code |= ERR_ALERT | ERR_FATAL;
6141 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006142 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006143 free(curproxy->conn_src.iface_name);
6144 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
6145 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006146 global.last_checks |= LSTCHK_NETADM;
6147#else
6148 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
6149 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02006150 err_code |= ERR_ALERT | ERR_FATAL;
6151 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01006152#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006153 cur_arg += 2;
6154 continue;
6155 }
6156 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02006157 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006158 err_code |= ERR_ALERT | ERR_FATAL;
6159 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006160 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006161 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006162 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
6163 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
6164 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02006165 err_code |= ERR_ALERT | ERR_FATAL;
6166 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006167 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006168 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006169 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006170 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6171 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006172 err_code |= ERR_ALERT | ERR_FATAL;
6173 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006174 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006175
6176 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006177 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006178 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006179 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006180 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006181 }
6182 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006183 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006184 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006185 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006186 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006187 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006188 }
6189 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006190 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006191 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006192 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006193 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006194 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006195 }
6196 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006197 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006198 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006199 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006200 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006201 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006202 }
6203 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006204 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006205 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006206 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006207 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006208 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006209 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006210 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006211 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006212 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006213 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006214 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006215 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006216 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006217 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006218 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006219 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6220 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006221 err_code |= ERR_ALERT | ERR_FATAL;
6222 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006223 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006224
6225 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006226 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006227 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006228 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006229 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006230 }
6231 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006232 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006233 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006234 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006235 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006236 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006237 }
6238 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
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_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006241 args[0], args[1], NULL, (const char **)args+2);
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], "reqipass")) { /* pass this header without allowing or denying the request */
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_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +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], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
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_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +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 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006259 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006260 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006261 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006262 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006263 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006264 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006265 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006266 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006267 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006268
Willy Tarreaubaaee002006-06-26 02:48:02 +02006269 if (curproxy == &defproxy) {
6270 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006271 err_code |= ERR_ALERT | ERR_FATAL;
6272 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006273 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006274 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006275 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006276
Willy Tarreaubaaee002006-06-26 02:48:02 +02006277 if (*(args[1]) == 0) {
6278 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006279 err_code |= ERR_ALERT | ERR_FATAL;
6280 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006281 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006282
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006283 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006284 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6285 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6286 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006287 err_code |= ERR_ALERT | ERR_FATAL;
6288 goto out;
6289 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006290 err_code |= warnif_cond_conflicts(cond,
6291 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6292 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006293 }
6294 else if (*args[2]) {
6295 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6296 file, linenum, args[0], args[2]);
6297 err_code |= ERR_ALERT | ERR_FATAL;
6298 goto out;
6299 }
6300
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006301 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006302 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006303 wl->s = strdup(args[1]);
6304 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02006305 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006306 }
6307 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006308 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006309 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6310 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006311 err_code |= ERR_ALERT | ERR_FATAL;
6312 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006313 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006314
Willy Tarreauade5ec42010-01-28 19:33:49 +01006315 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006316 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006317 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006318 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006319 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006320 }
6321 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006322 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006323 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006324 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006325 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006326 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006327 }
6328 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006329 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006330 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006331 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006332 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006333 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006334 }
6335 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006336 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006337 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6338 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006339 err_code |= ERR_ALERT | ERR_FATAL;
6340 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006341 }
6342
Willy Tarreauade5ec42010-01-28 19:33:49 +01006343 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006344 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006345 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006346 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006347 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006348 }
6349 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006350 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006351 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006352 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006353 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006354 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006355 }
6356 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006357 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006358 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006359 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006360 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006361 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006362 }
6363 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006364 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006365
Willy Tarreaubaaee002006-06-26 02:48:02 +02006366 if (curproxy == &defproxy) {
6367 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006368 err_code |= ERR_ALERT | ERR_FATAL;
6369 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006370 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006371 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006372 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006373
Willy Tarreaubaaee002006-06-26 02:48:02 +02006374 if (*(args[1]) == 0) {
6375 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006376 err_code |= ERR_ALERT | ERR_FATAL;
6377 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006378 }
6379
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006380 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006381 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6382 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6383 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006384 err_code |= ERR_ALERT | ERR_FATAL;
6385 goto out;
6386 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006387 err_code |= warnif_cond_conflicts(cond,
6388 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
6389 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006390 }
6391 else if (*args[2]) {
6392 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6393 file, linenum, args[0], args[2]);
6394 err_code |= ERR_ALERT | ERR_FATAL;
6395 goto out;
6396 }
6397
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006398 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006399 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006400 wl->s = strdup(args[1]);
6401 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006402 }
6403 else if (!strcmp(args[0], "errorloc") ||
6404 !strcmp(args[0], "errorloc302") ||
6405 !strcmp(args[0], "errorloc303")) { /* error location */
6406 int errnum, errlen;
6407 char *err;
6408
Willy Tarreau977b8e42006-12-29 14:19:17 +01006409 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006410 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006411
Willy Tarreaubaaee002006-06-26 02:48:02 +02006412 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006413 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006414 err_code |= ERR_ALERT | ERR_FATAL;
6415 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006416 }
6417
6418 errnum = atol(args[1]);
6419 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006420 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
6421 err = malloc(errlen);
6422 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006423 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006424 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
6425 err = malloc(errlen);
6426 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006427 }
6428
Willy Tarreau0f772532006-12-23 20:51:41 +01006429 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6430 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006431 chunk_destroy(&curproxy->errmsg[rc]);
6432 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01006433 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006434 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006435 }
Willy Tarreau0f772532006-12-23 20:51:41 +01006436
6437 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006438 Warning("parsing [%s:%d] : status code %d not handled by '%s', error relocation will be ignored.\n",
6439 file, linenum, errnum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006440 free(err);
6441 }
6442 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02006443 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
6444 int errnum, errlen, fd;
6445 char *err;
6446 struct stat stat;
6447
6448 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006449 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006450
6451 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006452 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006453 err_code |= ERR_ALERT | ERR_FATAL;
6454 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006455 }
6456
6457 fd = open(args[2], O_RDONLY);
6458 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
6459 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
6460 file, linenum, args[2], args[1]);
6461 if (fd >= 0)
6462 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02006463 err_code |= ERR_ALERT | ERR_FATAL;
6464 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006465 }
6466
Willy Tarreau27a674e2009-08-17 07:23:33 +02006467 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02006468 errlen = stat.st_size;
6469 } else {
6470 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02006471 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02006472 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02006473 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006474 }
6475
6476 err = malloc(errlen); /* malloc() must succeed during parsing */
6477 errnum = read(fd, err, errlen);
6478 if (errnum != errlen) {
6479 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
6480 file, linenum, args[2], args[1]);
6481 close(fd);
6482 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02006483 err_code |= ERR_ALERT | ERR_FATAL;
6484 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006485 }
6486 close(fd);
6487
6488 errnum = atol(args[1]);
6489 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6490 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006491 chunk_destroy(&curproxy->errmsg[rc]);
6492 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02006493 break;
6494 }
6495 }
6496
6497 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006498 Warning("parsing [%s:%d] : status code %d not handled by '%s', error customization will be ignored.\n",
6499 file, linenum, errnum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006500 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006501 free(err);
6502 }
6503 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006504 else if (!strcmp(args[0], "compression")) {
6505 struct comp *comp;
6506 if (curproxy->comp == NULL) {
6507 comp = calloc(1, sizeof(struct comp));
6508 curproxy->comp = comp;
6509 } else {
6510 comp = curproxy->comp;
6511 }
6512
6513 if (!strcmp(args[1], "algo")) {
6514 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01006515 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01006516
William Lallemand82fe75c2012-10-23 10:25:10 +02006517 cur_arg = 2;
6518 if (!*args[cur_arg]) {
6519 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
6520 file, linenum, args[0]);
6521 err_code |= ERR_ALERT | ERR_FATAL;
6522 goto out;
6523 }
6524 while (*(args[cur_arg])) {
6525 if (comp_append_algo(comp, args[cur_arg]) < 0) {
6526 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
6527 file, linenum, args[0], args[cur_arg]);
6528 err_code |= ERR_ALERT | ERR_FATAL;
6529 goto out;
6530 }
William Lallemand552df672012-11-07 13:21:47 +01006531 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
6532 curproxy->comp->algos->end(&ctx);
6533 } else {
6534 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
6535 file, linenum, args[0], args[cur_arg]);
6536 err_code |= ERR_ALERT | ERR_FATAL;
6537 goto out;
6538 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006539 cur_arg ++;
6540 continue;
6541 }
6542 }
Willy Tarreau70737d12012-10-27 00:34:28 +02006543 else if (!strcmp(args[1], "offload")) {
6544 comp->offload = 1;
6545 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006546 else if (!strcmp(args[1], "type")) {
6547 int cur_arg;
6548 cur_arg = 2;
6549 if (!*args[cur_arg]) {
6550 Alert("parsing [%s:%d] : '%s' expects <type>\n",
6551 file, linenum, args[0]);
6552 err_code |= ERR_ALERT | ERR_FATAL;
6553 goto out;
6554 }
6555 while (*(args[cur_arg])) {
6556 comp_append_type(comp, args[cur_arg]);
6557 cur_arg ++;
6558 continue;
6559 }
6560 }
6561 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02006562 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02006563 file, linenum, args[0]);
6564 err_code |= ERR_ALERT | ERR_FATAL;
6565 goto out;
6566 }
6567 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006568 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006569 struct cfg_kw_list *kwl;
6570 int index;
6571
6572 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6573 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6574 if (kwl->kw[index].section != CFG_LISTEN)
6575 continue;
6576 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6577 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006578 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006579 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006580 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006581 err_code |= ERR_ALERT | ERR_FATAL;
6582 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006583 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006584 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006585 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006586 err_code |= ERR_WARN;
6587 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006588 }
Willy Tarreau93893792009-07-23 13:19:11 +02006589 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006590 }
6591 }
6592 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006593
Willy Tarreau6daf3432008-01-22 16:44:08 +01006594 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006595 err_code |= ERR_ALERT | ERR_FATAL;
6596 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006597 }
Willy Tarreau93893792009-07-23 13:19:11 +02006598 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006599 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006600 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006601}
6602
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006603int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006604cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
6605{
6606#ifdef CONFIG_HAP_NS
6607 const char *err;
6608 const char *item = args[0];
6609
6610 if (!strcmp(item, "namespace_list")) {
6611 return 0;
6612 }
6613 else if (!strcmp(item, "namespace")) {
6614 size_t idx = 1;
6615 const char *current;
6616 while (*(current = args[idx++])) {
6617 err = invalid_char(current);
6618 if (err) {
6619 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6620 file, linenum, *err, item, current);
6621 return ERR_ALERT | ERR_FATAL;
6622 }
6623
6624 if (netns_store_lookup(current, strlen(current))) {
6625 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
6626 file, linenum, current);
6627 return ERR_ALERT | ERR_FATAL;
6628 }
6629 if (!netns_store_insert(current)) {
6630 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
6631 file, linenum, current);
6632 return ERR_ALERT | ERR_FATAL;
6633 }
6634 }
6635 }
6636
6637 return 0;
6638#else
6639 Alert("parsing [%s:%d]: namespace support is not compiled in.",
6640 file, linenum);
6641 return ERR_ALERT | ERR_FATAL;
6642#endif
6643}
6644
6645int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006646cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6647{
6648
6649 int err_code = 0;
6650 const char *err;
6651
6652 if (!strcmp(args[0], "userlist")) { /* new userlist */
6653 struct userlist *newul;
6654
6655 if (!*args[1]) {
6656 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6657 file, linenum, args[0]);
6658 err_code |= ERR_ALERT | ERR_FATAL;
6659 goto out;
6660 }
William Lallemand6e62fb62015-04-28 16:55:23 +02006661 if (alertif_too_many_args(1, file, linenum, args, &err_code))
6662 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006663
6664 err = invalid_char(args[1]);
6665 if (err) {
6666 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6667 file, linenum, *err, args[0], args[1]);
6668 err_code |= ERR_ALERT | ERR_FATAL;
6669 goto out;
6670 }
6671
6672 for (newul = userlist; newul; newul = newul->next)
6673 if (!strcmp(newul->name, args[1])) {
6674 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6675 file, linenum, args[1]);
6676 err_code |= ERR_WARN;
6677 goto out;
6678 }
6679
6680 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
6681 if (!newul) {
6682 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6683 err_code |= ERR_ALERT | ERR_ABORT;
6684 goto out;
6685 }
6686
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006687 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006688 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006689 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6690 err_code |= ERR_ALERT | ERR_ABORT;
6691 goto out;
6692 }
6693
6694 newul->next = userlist;
6695 userlist = newul;
6696
6697 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006698 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006699 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006700 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006701
6702 if (!*args[1]) {
6703 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6704 file, linenum, args[0]);
6705 err_code |= ERR_ALERT | ERR_FATAL;
6706 goto out;
6707 }
6708
6709 err = invalid_char(args[1]);
6710 if (err) {
6711 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6712 file, linenum, *err, args[0], args[1]);
6713 err_code |= ERR_ALERT | ERR_FATAL;
6714 goto out;
6715 }
6716
William Lallemand4ac9f542015-05-28 18:03:51 +02006717 if (!userlist)
6718 goto out;
6719
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006720 for (ag = userlist->groups; ag; ag = ag->next)
6721 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006722 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6723 file, linenum, args[1], userlist->name);
6724 err_code |= ERR_ALERT;
6725 goto out;
6726 }
6727
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006728 ag = calloc(1, sizeof(*ag));
6729 if (!ag) {
6730 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6731 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006732 goto out;
6733 }
6734
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006735 ag->name = strdup(args[1]);
6736 if (!ag) {
6737 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6738 err_code |= ERR_ALERT | ERR_ABORT;
6739 goto out;
6740 }
6741
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006742 cur_arg = 2;
6743
6744 while (*args[cur_arg]) {
6745 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006746 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006747 cur_arg += 2;
6748 continue;
6749 } else {
6750 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6751 file, linenum, args[0]);
6752 err_code |= ERR_ALERT | ERR_FATAL;
6753 goto out;
6754 }
6755 }
6756
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006757 ag->next = userlist->groups;
6758 userlist->groups = ag;
6759
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006760 } else if (!strcmp(args[0], "user")) { /* new user */
6761 struct auth_users *newuser;
6762 int cur_arg;
6763
6764 if (!*args[1]) {
6765 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6766 file, linenum, args[0]);
6767 err_code |= ERR_ALERT | ERR_FATAL;
6768 goto out;
6769 }
William Lallemand4ac9f542015-05-28 18:03:51 +02006770 if (!userlist)
6771 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006772
6773 for (newuser = userlist->users; newuser; newuser = newuser->next)
6774 if (!strcmp(newuser->user, args[1])) {
6775 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6776 file, linenum, args[1], userlist->name);
6777 err_code |= ERR_ALERT;
6778 goto out;
6779 }
6780
6781 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
6782 if (!newuser) {
6783 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6784 err_code |= ERR_ALERT | ERR_ABORT;
6785 goto out;
6786 }
6787
6788 newuser->user = strdup(args[1]);
6789
6790 newuser->next = userlist->users;
6791 userlist->users = newuser;
6792
6793 cur_arg = 2;
6794
6795 while (*args[cur_arg]) {
6796 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006797#ifdef CONFIG_HAP_CRYPT
6798 if (!crypt("", args[cur_arg + 1])) {
6799 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6800 file, linenum, newuser->user);
6801 err_code |= ERR_ALERT | ERR_FATAL;
6802 goto out;
6803 }
6804#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006805 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6806 file, linenum);
6807 err_code |= ERR_ALERT;
6808#endif
6809 newuser->pass = strdup(args[cur_arg + 1]);
6810 cur_arg += 2;
6811 continue;
6812 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6813 newuser->pass = strdup(args[cur_arg + 1]);
6814 newuser->flags |= AU_O_INSECURE;
6815 cur_arg += 2;
6816 continue;
6817 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006818 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006819 cur_arg += 2;
6820 continue;
6821 } else {
6822 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6823 file, linenum, args[0]);
6824 err_code |= ERR_ALERT | ERR_FATAL;
6825 goto out;
6826 }
6827 }
6828 } else {
6829 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6830 err_code |= ERR_ALERT | ERR_FATAL;
6831 }
6832
6833out:
6834 return err_code;
6835}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006836
6837/*
6838 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006839 * Returns the error code, 0 if OK, or any combination of :
6840 * - ERR_ABORT: must abort ASAP
6841 * - ERR_FATAL: we can continue parsing but not start the service
6842 * - ERR_WARN: a warning has been emitted
6843 * - ERR_ALERT: an alert has been emitted
6844 * Only the two first ones can stop processing, the two others are just
6845 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006846 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006847int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006848{
William Lallemand64e84512015-05-12 14:25:37 +02006849 char *thisline;
6850 int linesize = LINESIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006851 FILE *f;
6852 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02006853 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006854 struct cfg_section *cs = NULL;
6855 struct cfg_section *ics;
William Lallemand64e84512015-05-12 14:25:37 +02006856 int readbytes = 0;
6857
6858 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
William Lallemandb2f07452015-05-12 14:27:13 +02006859 Alert("parsing [%s] : out of memory.\n", file);
William Lallemand64e84512015-05-12 14:25:37 +02006860 return -1;
6861 }
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006862
6863 /* Register internal sections */
6864 if (!cfg_register_section("listen", cfg_parse_listen) ||
6865 !cfg_register_section("frontend", cfg_parse_listen) ||
6866 !cfg_register_section("backend", cfg_parse_listen) ||
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006867 !cfg_register_section("defaults", cfg_parse_listen) ||
6868 !cfg_register_section("global", cfg_parse_global) ||
6869 !cfg_register_section("userlist", cfg_parse_users) ||
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006870 !cfg_register_section("peers", cfg_parse_peers) ||
Simon Horman0d16a402015-01-30 11:22:58 +09006871 !cfg_register_section("mailers", cfg_parse_mailers) ||
Baptiste Assmann325137d2015-04-13 23:40:55 +02006872 !cfg_register_section("namespace_list", cfg_parse_netns) ||
6873 !cfg_register_section("resolvers", cfg_parse_resolvers))
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006874 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006875
Willy Tarreaubaaee002006-06-26 02:48:02 +02006876 if ((f=fopen(file,"r")) == NULL)
6877 return -1;
6878
William Lallemandb2f07452015-05-12 14:27:13 +02006879next_line:
William Lallemand64e84512015-05-12 14:25:37 +02006880 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02006881 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006882 char *end;
6883 char *args[MAX_LINE_ARGS + 1];
6884 char *line = thisline;
William Lallemandf9873ba2015-05-05 17:37:14 +02006885 int dquote = 0; /* double quote */
6886 int squote = 0; /* simple quote */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006887
Willy Tarreaubaaee002006-06-26 02:48:02 +02006888 linenum++;
6889
6890 end = line + strlen(line);
6891
William Lallemand64e84512015-05-12 14:25:37 +02006892 if (end-line == linesize-1 && *(end-1) != '\n') {
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006893 /* Check if we reached the limit and the last char is not \n.
6894 * Watch out for the last line without the terminating '\n'!
6895 */
William Lallemand64e84512015-05-12 14:25:37 +02006896 char *newline;
6897 int newlinesize = linesize * 2;
6898
6899 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
6900 if (newline == NULL) {
6901 Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
6902 file, linenum);
6903 err_code |= ERR_ALERT | ERR_FATAL;
6904 continue;
6905 }
6906
6907 readbytes = linesize - 1;
6908 linesize = newlinesize;
6909 thisline = newline;
6910 continue;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006911 }
6912
William Lallemand64e84512015-05-12 14:25:37 +02006913 readbytes = 0;
6914
Willy Tarreaubaaee002006-06-26 02:48:02 +02006915 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006916 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006917 line++;
William Lallemandf9873ba2015-05-05 17:37:14 +02006918
Willy Tarreaubaaee002006-06-26 02:48:02 +02006919 arg = 0;
6920 args[arg] = line;
6921
6922 while (*line && arg < MAX_LINE_ARGS) {
William Lallemandf9873ba2015-05-05 17:37:14 +02006923 if (*line == '"' && !squote) { /* double quote outside single quotes */
6924 if (dquote)
6925 dquote = 0;
6926 else
6927 dquote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02006928 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02006929 end--;
6930 }
6931 else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
6932 if (squote)
6933 squote = 0;
6934 else
6935 squote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02006936 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02006937 end--;
6938 }
6939 else if (*line == '\\' && !squote) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006940 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
6941 * C equivalent value. Other combinations left unchanged (eg: \1).
6942 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006943 int skip = 0;
6944 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
6945 *line = line[1];
6946 skip = 1;
6947 }
6948 else if (line[1] == 'r') {
6949 *line = '\r';
6950 skip = 1;
William Lallemandf9873ba2015-05-05 17:37:14 +02006951 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006952 else if (line[1] == 'n') {
6953 *line = '\n';
6954 skip = 1;
6955 }
6956 else if (line[1] == 't') {
6957 *line = '\t';
6958 skip = 1;
6959 }
6960 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01006961 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006962 unsigned char hex1, hex2;
6963 hex1 = toupper(line[2]) - '0';
6964 hex2 = toupper(line[3]) - '0';
6965 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
6966 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
6967 *line = (hex1<<4) + hex2;
6968 skip = 3;
6969 }
6970 else {
6971 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006972 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006973 }
William Lallemandf9873ba2015-05-05 17:37:14 +02006974 } else if (line[1] == '"') {
6975 *line = '"';
6976 skip = 1;
6977 } else if (line[1] == '\'') {
6978 *line = '\'';
6979 skip = 1;
William Lallemandb2f07452015-05-12 14:27:13 +02006980 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
6981 *line = '$';
6982 skip = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006983 }
6984 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01006985 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006986 end -= skip;
6987 }
6988 line++;
6989 }
William Lallemandf9873ba2015-05-05 17:37:14 +02006990 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006991 /* end of string, end of loop */
6992 *line = 0;
6993 break;
6994 }
William Lallemandf9873ba2015-05-05 17:37:14 +02006995 else if (!squote && !dquote && isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006996 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006997 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006998 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006999 line++;
7000 args[++arg] = line;
7001 }
William Lallemandb2f07452015-05-12 14:27:13 +02007002 else if (dquote && *line == '$') {
7003 /* environment variables are evaluated inside double quotes */
7004 char *var_beg;
7005 char *var_end;
7006 char save_char;
7007 char *value;
7008 int val_len;
7009 int newlinesize;
7010 int braces = 0;
7011
7012 var_beg = line + 1;
7013 var_end = var_beg;
7014
7015 if (*var_beg == '{') {
7016 var_beg++;
7017 var_end++;
7018 braces = 1;
7019 }
7020
7021 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
7022 Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
7023 err_code |= ERR_ALERT | ERR_FATAL;
7024 goto next_line; /* skip current line */
7025 }
7026
7027 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
7028 var_end++;
7029
7030 save_char = *var_end;
7031 *var_end = '\0';
7032 value = getenv(var_beg);
7033 *var_end = save_char;
7034 val_len = value ? strlen(value) : 0;
7035
7036 if (braces) {
7037 if (*var_end == '}') {
7038 var_end++;
7039 braces = 0;
7040 } else {
7041 Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
7042 err_code |= ERR_ALERT | ERR_FATAL;
7043 goto next_line; /* skip current line */
7044 }
7045 }
7046
7047 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
7048
7049 /* if not enough space in thisline */
7050 if (newlinesize > linesize) {
7051 char *newline;
7052
7053 newline = realloc(thisline, newlinesize * sizeof(*thisline));
7054 if (newline == NULL) {
7055 Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
7056 err_code |= ERR_ALERT | ERR_FATAL;
7057 goto next_line; /* slip current line */
7058 }
7059 /* recompute pointers if realloc returns a new pointer */
7060 if (newline != thisline) {
7061 int i;
7062 int diff;
7063
7064 for (i = 0; i <= arg; i++) {
7065 diff = args[i] - thisline;
7066 args[i] = newline + diff;
7067 }
7068
7069 diff = var_end - thisline;
7070 var_end = newline + diff;
7071 diff = end - thisline;
7072 end = newline + diff;
7073 diff = line - thisline;
7074 line = newline + diff;
7075 thisline = newline;
7076 }
7077 linesize = newlinesize;
7078 }
7079
7080 /* insert value inside the line */
7081 memmove(line + val_len, var_end, end - var_end + 1);
7082 memcpy(line, value, val_len);
7083 end += val_len - (var_end - line);
7084 line += val_len;
7085 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007086 else {
7087 line++;
7088 }
7089 }
William Lallemandb2f07452015-05-12 14:27:13 +02007090
William Lallemandf9873ba2015-05-05 17:37:14 +02007091 if (dquote) {
7092 Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
7093 err_code |= ERR_ALERT | ERR_FATAL;
7094 }
7095
7096 if (squote) {
7097 Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
7098 err_code |= ERR_ALERT | ERR_FATAL;
7099 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007100
7101 /* empty line */
7102 if (!**args)
7103 continue;
7104
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007105 if (*line) {
7106 /* we had to stop due to too many args.
7107 * Let's terminate the string, print the offending part then cut the
7108 * last arg.
7109 */
7110 while (*line && *line != '#' && *line != '\n' && *line != '\r')
7111 line++;
7112 *line = '\0';
7113
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01007114 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01007115 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007116 err_code |= ERR_ALERT | ERR_FATAL;
7117 args[arg] = line;
7118 }
7119
Willy Tarreau540abe42007-05-02 20:50:16 +02007120 /* zero out remaining args and ensure that at least one entry
7121 * is zeroed out.
7122 */
7123 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007124 args[arg] = line;
7125 }
7126
Willy Tarreau3842f002009-06-14 11:39:52 +02007127 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007128 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02007129 char *tmp;
7130
Willy Tarreau3842f002009-06-14 11:39:52 +02007131 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02007132 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007133 for (arg=0; *args[arg+1]; arg++)
7134 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02007135 *tmp = '\0'; // fix the next arg to \0
7136 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007137 }
Willy Tarreau3842f002009-06-14 11:39:52 +02007138 else if (!strcmp(args[0], "default")) {
7139 kwm = KWM_DEF;
7140 for (arg=0; *args[arg+1]; arg++)
7141 args[arg] = args[arg+1]; // shift args after inversion
7142 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007143
William Lallemand0f99e342011-10-12 17:50:54 +02007144 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
7145 strcmp(args[0], "log") != 0) {
7146 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02007147 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007148 }
7149
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007150 /* detect section start */
7151 list_for_each_entry(ics, &sections, list) {
7152 if (strcmp(args[0], ics->section_name) == 0) {
7153 cursection = ics->section_name;
7154 cs = ics;
7155 break;
7156 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007157 }
7158
Willy Tarreaubaaee002006-06-26 02:48:02 +02007159 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007160 if (cs)
7161 err_code |= cs->section_parser(file, linenum, args, kwm);
7162 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007163 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007164 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007165 }
Willy Tarreau058e9072009-07-20 09:30:05 +02007166
7167 if (err_code & ERR_ABORT)
7168 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007169 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01007170 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02007171 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007172 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02007173 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007174}
7175
Willy Tarreau64ab6072014-09-16 12:17:36 +02007176/* This function propagates processes from frontend <from> to backend <to> so
7177 * that it is always guaranteed that a backend pointed to by a frontend is
7178 * bound to all of its processes. After that, if the target is a "listen"
7179 * instance, the function recursively descends the target's own targets along
Willy Tarreau98d04852015-05-26 12:18:29 +02007180 * default_backend and use_backend rules. Since the bits are
Willy Tarreau64ab6072014-09-16 12:17:36 +02007181 * checked first to ensure that <to> is already bound to all processes of
7182 * <from>, there is no risk of looping and we ensure to follow the shortest
7183 * path to the destination.
7184 *
7185 * It is possible to set <to> to NULL for the first call so that the function
7186 * takes care of visiting the initial frontend in <from>.
7187 *
7188 * It is important to note that the function relies on the fact that all names
7189 * have already been resolved.
7190 */
7191void propagate_processes(struct proxy *from, struct proxy *to)
7192{
7193 struct switching_rule *rule;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007194
7195 if (to) {
7196 /* check whether we need to go down */
7197 if (from->bind_proc &&
7198 (from->bind_proc & to->bind_proc) == from->bind_proc)
7199 return;
7200
7201 if (!from->bind_proc && !to->bind_proc)
7202 return;
7203
7204 to->bind_proc = from->bind_proc ?
7205 (to->bind_proc | from->bind_proc) : 0;
7206
7207 /* now propagate down */
7208 from = to;
7209 }
7210
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01007211 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02007212 return;
7213
Willy Tarreauf6b70012014-12-18 14:00:43 +01007214 if (from->state == PR_STSTOPPED)
7215 return;
7216
Willy Tarreau64ab6072014-09-16 12:17:36 +02007217 /* default_backend */
7218 if (from->defbe.be)
7219 propagate_processes(from, from->defbe.be);
7220
7221 /* use_backend */
7222 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02007223 if (rule->dynamic)
7224 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007225 to = rule->be.backend;
7226 propagate_processes(from, to);
7227 }
Willy Tarreau64ab6072014-09-16 12:17:36 +02007228}
7229
Willy Tarreaubb925012009-07-23 13:36:36 +02007230/*
7231 * Returns the error code, 0 if OK, or any combination of :
7232 * - ERR_ABORT: must abort ASAP
7233 * - ERR_FATAL: we can continue parsing but not start the service
7234 * - ERR_WARN: a warning has been emitted
7235 * - ERR_ALERT: an alert has been emitted
7236 * Only the two first ones can stop processing, the two others are just
7237 * indicators.
7238 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007239int check_config_validity()
7240{
7241 int cfgerr = 0;
7242 struct proxy *curproxy = NULL;
7243 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02007244 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007245 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007246 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007247
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007248 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007249 /*
7250 * Now, check for the integrity of all that we have collected.
7251 */
7252
7253 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02007254 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007255
Willy Tarreau193b8c62012-11-22 00:17:38 +01007256 if (!global.tune.max_http_hdr)
7257 global.tune.max_http_hdr = MAX_HTTP_HDR;
7258
7259 if (!global.tune.cookie_len)
7260 global.tune.cookie_len = CAPTURE_LEN;
7261
7262 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
7263
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007264 /* Post initialisation of the users and groups lists. */
7265 err_code = userlist_postinit();
7266 if (err_code != ERR_NONE)
7267 goto out;
7268
Willy Tarreau55bc0f82009-03-15 14:51:53 +01007269 /* first, we will invert the proxy list order */
7270 curproxy = NULL;
7271 while (proxy) {
7272 struct proxy *next;
7273
7274 next = proxy->next;
7275 proxy->next = curproxy;
7276 curproxy = proxy;
7277 if (!next)
7278 break;
7279 proxy = next;
7280 }
7281
Willy Tarreau419ead82014-09-16 13:41:21 +02007282 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007283 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007284 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01007285 struct sticking_rule *mrule;
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007286 struct act_rule *trule;
7287 struct act_rule *hrqrule;
Dragan Dosen1322d092015-09-22 16:05:32 +02007288 struct logsrv *tmplogsrv;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007289 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01007290 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007291
Willy Tarreau050536d2012-10-04 08:47:34 +02007292 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007293 /* proxy ID not set, use automatic numbering with first
7294 * spare entry starting with next_pxid.
7295 */
7296 next_pxid = get_next_id(&used_proxy_id, next_pxid);
7297 curproxy->conf.id.key = curproxy->uuid = next_pxid;
7298 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007299 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007300 next_pxid++;
7301
Willy Tarreau55ea7572007-06-17 19:56:27 +02007302
Willy Tarreaubaaee002006-06-26 02:48:02 +02007303 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02007304 /* ensure we don't keep listeners uselessly bound */
7305 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02007306 free((void *)curproxy->table.peers.name);
7307 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007308 continue;
7309 }
7310
Willy Tarreau102df612014-05-07 23:56:38 +02007311 /* Check multi-process mode compatibility for the current proxy */
7312
7313 if (curproxy->bind_proc) {
7314 /* an explicit bind-process was specified, let's check how many
7315 * processes remain.
7316 */
David Carliere6c39412015-07-02 07:00:17 +00007317 nbproc = my_popcountl(curproxy->bind_proc);
Willy Tarreau102df612014-05-07 23:56:38 +02007318
7319 curproxy->bind_proc &= nbits(global.nbproc);
7320 if (!curproxy->bind_proc && nbproc == 1) {
7321 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);
7322 curproxy->bind_proc = 1;
7323 }
7324 else if (!curproxy->bind_proc && nbproc > 1) {
7325 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);
7326 curproxy->bind_proc = 0;
7327 }
7328 }
7329
Willy Tarreau3d209582014-05-09 17:06:11 +02007330 /* check and reduce the bind-proc of each listener */
7331 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7332 unsigned long mask;
7333
7334 if (!bind_conf->bind_proc)
7335 continue;
7336
7337 mask = nbits(global.nbproc);
7338 if (curproxy->bind_proc)
7339 mask &= curproxy->bind_proc;
7340 /* mask cannot be null here thanks to the previous checks */
7341
David Carliere6c39412015-07-02 07:00:17 +00007342 nbproc = my_popcountl(bind_conf->bind_proc);
Willy Tarreau3d209582014-05-09 17:06:11 +02007343 bind_conf->bind_proc &= mask;
7344
7345 if (!bind_conf->bind_proc && nbproc == 1) {
7346 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",
7347 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7348 bind_conf->bind_proc = mask & ~(mask - 1);
7349 }
7350 else if (!bind_conf->bind_proc && nbproc > 1) {
7351 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",
7352 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7353 bind_conf->bind_proc = 0;
7354 }
7355 }
7356
Willy Tarreauff01a212009-03-15 13:46:16 +01007357 switch (curproxy->mode) {
7358 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007359 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007360 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007361 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
7362 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007363 cfgerr++;
7364 }
7365
7366 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007367 Warning("config : servers will be ignored for %s '%s'.\n",
7368 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007369 break;
7370
7371 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007372 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007373 break;
7374
7375 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01007376 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01007377 break;
7378 }
7379
Willy Tarreauf3934b82015-08-11 11:36:45 +02007380 if ((curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->conf.listeners)) {
7381 Warning("config : %s '%s' has no 'bind' directive. Please declare it as a backend if this was intended.\n",
7382 proxy_type_str(curproxy), curproxy->id);
7383 err_code |= ERR_WARN;
7384 }
7385
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007386 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007387 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007388 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007389 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
7390 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007391 cfgerr++;
7392 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007393#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007394 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007395 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
7396 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007397 cfgerr++;
7398 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007399#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02007400 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007401 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
7402 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007403 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007404 }
7405 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02007406 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007407 /* If no LB algo is set in a backend, and we're not in
7408 * transparent mode, dispatch mode nor proxy mode, we
7409 * want to use balance roundrobin by default.
7410 */
7411 curproxy->lbprm.algo &= ~BE_LB_ALGO;
7412 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007413 }
7414 }
Willy Tarreau193cf932007-09-17 10:17:23 +02007415
Willy Tarreau1620ec32011-08-06 17:05:02 +02007416 if (curproxy->options & PR_O_DISPATCH)
7417 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
7418 else if (curproxy->options & PR_O_HTTP_PROXY)
7419 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
7420 else if (curproxy->options & PR_O_TRANSP)
7421 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01007422
Willy Tarreau1620ec32011-08-06 17:05:02 +02007423 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
7424 if (curproxy->options & PR_O_DISABLE404) {
7425 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7426 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
7427 err_code |= ERR_WARN;
7428 curproxy->options &= ~PR_O_DISABLE404;
7429 }
7430 if (curproxy->options2 & PR_O2_CHK_SNDST) {
7431 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7432 "send-state", proxy_type_str(curproxy), curproxy->id);
7433 err_code |= ERR_WARN;
7434 curproxy->options &= ~PR_O2_CHK_SNDST;
7435 }
Willy Tarreauef781042010-01-27 11:53:01 +01007436 }
7437
Simon Horman98637e52014-06-20 12:30:16 +09007438 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
7439 if (!global.external_check) {
7440 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
7441 curproxy->id, "option external-check");
7442 cfgerr++;
7443 }
7444 if (!curproxy->check_command) {
7445 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
7446 curproxy->id, "option external-check");
7447 cfgerr++;
7448 }
7449 }
7450
Simon Horman64e34162015-02-06 11:11:57 +09007451 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007452 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
7453 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Pieter Baauw8669e972015-08-17 00:45:05 +02007454 "'email-alert from', 'email-alert level' 'email-alert mailers', "
7455 "'email-alert myhostname', or 'email-alert to' "
7456 "requires each of 'email-alert from', 'email-alert mailers' and 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007457 "to be present).\n",
7458 proxy_type_str(curproxy), curproxy->id);
7459 err_code |= ERR_WARN;
7460 free_email_alert(curproxy);
7461 }
7462 if (!curproxy->email_alert.myhostname)
7463 curproxy->email_alert.myhostname = hostname;
Simon Horman9dc49962015-01-30 11:22:59 +09007464 }
7465
Simon Horman98637e52014-06-20 12:30:16 +09007466 if (curproxy->check_command) {
7467 int clear = 0;
7468 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7469 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7470 "external-check command", proxy_type_str(curproxy), curproxy->id);
7471 err_code |= ERR_WARN;
7472 clear = 1;
7473 }
7474 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
Ben Cabot49795eb2015-09-16 12:07:51 +01007475 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-check path' is not set.\n",
Simon Horman98637e52014-06-20 12:30:16 +09007476 curproxy->id, "external-check command");
7477 cfgerr++;
7478 }
7479 if (clear) {
7480 free(curproxy->check_command);
7481 curproxy->check_command = NULL;
7482 }
7483 }
7484
7485 if (curproxy->check_path) {
7486 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7487 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7488 "external-check path", proxy_type_str(curproxy), curproxy->id);
7489 err_code |= ERR_WARN;
7490 free(curproxy->check_path);
7491 curproxy->check_path = NULL;
7492 }
7493 }
7494
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007495 /* if a default backend was specified, let's find it */
7496 if (curproxy->defbe.name) {
7497 struct proxy *target;
7498
Willy Tarreauafb39922015-05-26 12:04:09 +02007499 target = proxy_be_by_name(curproxy->defbe.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007500 if (!target) {
7501 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
7502 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007503 cfgerr++;
7504 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007505 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
7506 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02007507 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007508 } else if (target->mode != curproxy->mode &&
7509 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7510
7511 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) as its default backend (see 'mode').\n",
7512 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7513 curproxy->conf.file, curproxy->conf.line,
7514 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7515 target->conf.file, target->conf.line);
7516 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007517 } else {
7518 free(curproxy->defbe.name);
7519 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01007520
7521 /* Emit a warning if this proxy also has some servers */
7522 if (curproxy->srv) {
7523 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
7524 curproxy->id);
7525 err_code |= ERR_WARN;
7526 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007527 }
7528 }
7529
Willy Tarreau55ea7572007-06-17 19:56:27 +02007530 /* find the target proxy for 'use_backend' rules */
7531 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007532 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007533 struct logformat_node *node;
7534 char *pxname;
7535
7536 /* Try to parse the string as a log format expression. If the result
7537 * of the parsing is only one entry containing a simple string, then
7538 * it's a standard string corresponding to a static rule, thus the
7539 * parsing is cancelled and be.name is restored to be resolved.
7540 */
7541 pxname = rule->be.name;
7542 LIST_INIT(&rule->be.expr);
7543 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
7544 curproxy->conf.args.file, curproxy->conf.args.line);
7545 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
7546
7547 if (!LIST_ISEMPTY(&rule->be.expr)) {
7548 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
7549 rule->dynamic = 1;
7550 free(pxname);
7551 continue;
7552 }
7553 /* simple string: free the expression and fall back to static rule */
7554 free(node->arg);
7555 free(node);
7556 }
7557
7558 rule->dynamic = 0;
7559 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007560
Willy Tarreauafb39922015-05-26 12:04:09 +02007561 target = proxy_be_by_name(rule->be.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007562 if (!target) {
7563 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
7564 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007565 cfgerr++;
7566 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007567 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
7568 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007569 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007570 } else if (target->mode != curproxy->mode &&
7571 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7572
7573 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) in a 'use_backend' rule (see 'mode').\n",
7574 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7575 curproxy->conf.file, curproxy->conf.line,
7576 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7577 target->conf.file, target->conf.line);
7578 cfgerr++;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007579 } else {
7580 free((void *)rule->be.name);
7581 rule->be.backend = target;
7582 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007583 }
7584
Willy Tarreau64ab6072014-09-16 12:17:36 +02007585 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007586 list_for_each_entry(srule, &curproxy->server_rules, list) {
7587 struct server *target = findserver(curproxy, srule->srv.name);
7588
7589 if (!target) {
7590 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7591 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7592 cfgerr++;
7593 continue;
7594 }
7595 free((void *)srule->srv.name);
7596 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007597 }
7598
Emeric Brunb982a3d2010-01-04 15:45:53 +01007599 /* find the target table for 'stick' rules */
7600 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7601 struct proxy *target;
7602
Emeric Brun1d33b292010-01-04 15:47:17 +01007603 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7604 if (mrule->flags & STK_IS_STORE)
7605 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7606
Emeric Brunb982a3d2010-01-04 15:45:53 +01007607 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007608 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007609 else
7610 target = curproxy;
7611
7612 if (!target) {
7613 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7614 curproxy->id, mrule->table.name);
7615 cfgerr++;
7616 }
7617 else if (target->table.size == 0) {
7618 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7619 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7620 cfgerr++;
7621 }
Willy Tarreau12785782012-04-27 21:37:17 +02007622 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7623 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007624 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7625 cfgerr++;
7626 }
7627 else {
7628 free((void *)mrule->table.name);
7629 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007630 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007631 }
7632 }
7633
7634 /* find the target table for 'store response' rules */
7635 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7636 struct proxy *target;
7637
Emeric Brun1d33b292010-01-04 15:47:17 +01007638 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7639
Emeric Brunb982a3d2010-01-04 15:45:53 +01007640 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007641 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007642 else
7643 target = curproxy;
7644
7645 if (!target) {
7646 Alert("Proxy '%s': unable to find store table '%s'.\n",
7647 curproxy->id, mrule->table.name);
7648 cfgerr++;
7649 }
7650 else if (target->table.size == 0) {
7651 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7652 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7653 cfgerr++;
7654 }
Willy Tarreau12785782012-04-27 21:37:17 +02007655 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7656 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007657 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7658 cfgerr++;
7659 }
7660 else {
7661 free((void *)mrule->table.name);
7662 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007663 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007664 }
7665 }
7666
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007667 /* find the target table for 'tcp-request' layer 4 rules */
7668 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
7669 struct proxy *target;
7670
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007671 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007672 continue;
7673
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007674 if (trule->arg.trk_ctr.table.n)
7675 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007676 else
7677 target = curproxy;
7678
7679 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007680 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007681 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007682 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007683 cfgerr++;
7684 }
7685 else if (target->table.size == 0) {
7686 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007687 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007688 cfgerr++;
7689 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007690 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007691 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007692 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007693 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007694 cfgerr++;
7695 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007696 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007697 free(trule->arg.trk_ctr.table.n);
7698 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007699 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007700 * to pass a list of counters to track and allocate them right here using
7701 * stktable_alloc_data_type().
7702 */
7703 }
7704 }
7705
Willy Tarreaud1f96522010-08-03 19:34:32 +02007706 /* find the target table for 'tcp-request' layer 6 rules */
7707 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7708 struct proxy *target;
7709
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007710 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02007711 continue;
7712
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007713 if (trule->arg.trk_ctr.table.n)
7714 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007715 else
7716 target = curproxy;
7717
7718 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007719 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007720 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007721 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02007722 cfgerr++;
7723 }
7724 else if (target->table.size == 0) {
7725 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007726 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007727 cfgerr++;
7728 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007729 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007730 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007731 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007732 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007733 cfgerr++;
7734 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02007735 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007736 free(trule->arg.trk_ctr.table.n);
7737 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007738 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02007739 * to pass a list of counters to track and allocate them right here using
7740 * stktable_alloc_data_type().
7741 */
7742 }
7743 }
7744
Willy Tarreau09448f72014-06-25 18:12:15 +02007745 /* find the target table for 'http-request' layer 7 rules */
7746 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7747 struct proxy *target;
7748
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007749 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau09448f72014-06-25 18:12:15 +02007750 continue;
7751
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007752 if (hrqrule->arg.trk_ctr.table.n)
7753 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
Willy Tarreau09448f72014-06-25 18:12:15 +02007754 else
7755 target = curproxy;
7756
7757 if (!target) {
7758 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007759 curproxy->id, hrqrule->arg.trk_ctr.table.n,
Willy Tarreau09448f72014-06-25 18:12:15 +02007760 http_req_trk_idx(hrqrule->action));
7761 cfgerr++;
7762 }
7763 else if (target->table.size == 0) {
7764 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007765 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau09448f72014-06-25 18:12:15 +02007766 cfgerr++;
7767 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007768 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau09448f72014-06-25 18:12:15 +02007769 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007770 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau09448f72014-06-25 18:12:15 +02007771 http_req_trk_idx(hrqrule->action));
7772 cfgerr++;
7773 }
7774 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007775 free(hrqrule->arg.trk_ctr.table.n);
7776 hrqrule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau09448f72014-06-25 18:12:15 +02007777 /* Note: if we decide to enhance the track-sc syntax, we may be able
7778 * to pass a list of counters to track and allocate them right here using
7779 * stktable_alloc_data_type().
7780 */
7781 }
7782 }
7783
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02007784 /* move any "block" rules at the beginning of the http-request rules */
7785 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
7786 /* insert block_rules into http_req_rules at the beginning */
7787 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
7788 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
7789 curproxy->block_rules.n->p = &curproxy->http_req_rules;
7790 curproxy->http_req_rules.n = curproxy->block_rules.n;
7791 LIST_INIT(&curproxy->block_rules);
7792 }
7793
Emeric Brun32da3c42010-09-23 18:39:19 +02007794 if (curproxy->table.peers.name) {
7795 struct peers *curpeers = peers;
7796
7797 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
7798 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
7799 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01007800 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02007801 break;
7802 }
7803 }
7804
7805 if (!curpeers) {
7806 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
7807 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007808 free((void *)curproxy->table.peers.name);
7809 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007810 cfgerr++;
7811 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02007812 else if (curpeers->state == PR_STSTOPPED) {
7813 /* silently disable this peers section */
7814 curproxy->table.peers.p = NULL;
7815 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007816 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02007817 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
7818 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007819 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007820 cfgerr++;
7821 }
7822 }
7823
Simon Horman9dc49962015-01-30 11:22:59 +09007824
7825 if (curproxy->email_alert.mailers.name) {
7826 struct mailers *curmailers = mailers;
7827
7828 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
7829 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
7830 free(curproxy->email_alert.mailers.name);
7831 curproxy->email_alert.mailers.m = curmailers;
7832 curmailers->users++;
7833 break;
7834 }
7835 }
7836
7837 if (!curmailers) {
7838 Alert("Proxy '%s': unable to find mailers '%s'.\n",
7839 curproxy->id, curproxy->email_alert.mailers.name);
7840 free_email_alert(curproxy);
7841 cfgerr++;
7842 }
7843 }
7844
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007845 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01007846 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007847 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
7848 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
7849 "proxy", curproxy->id);
7850 cfgerr++;
7851 goto out_uri_auth_compat;
7852 }
7853
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007854 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007855 const char *uri_auth_compat_req[10];
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007856 struct act_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01007857 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007858
Willy Tarreau95fa4692010-02-01 13:05:50 +01007859 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
7860 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007861
7862 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007863 uri_auth_compat_req[i++] = "realm";
7864 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
7865 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007866
Willy Tarreau95fa4692010-02-01 13:05:50 +01007867 uri_auth_compat_req[i++] = "unless";
7868 uri_auth_compat_req[i++] = "{";
7869 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
7870 uri_auth_compat_req[i++] = "}";
7871 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007872
Willy Tarreauff011f22011-01-06 17:51:27 +01007873 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
7874 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007875 cfgerr++;
7876 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007877 }
7878
Willy Tarreauff011f22011-01-06 17:51:27 +01007879 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01007880
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007881 if (curproxy->uri_auth->auth_realm) {
7882 free(curproxy->uri_auth->auth_realm);
7883 curproxy->uri_auth->auth_realm = NULL;
7884 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007885
7886 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007887 }
7888out_uri_auth_compat:
7889
Dragan Dosen43885c72015-10-01 13:18:13 +02007890 /* check whether we have a log server that uses RFC5424 log format */
Dragan Dosen1322d092015-09-22 16:05:32 +02007891 list_for_each_entry(tmplogsrv, &curproxy->logsrvs, list) {
Dragan Dosen43885c72015-10-01 13:18:13 +02007892 if (tmplogsrv->format == LOG_FORMAT_RFC5424) {
7893 if (!curproxy->conf.logformat_sd_string) {
7894 /* set the default logformat_sd_string */
7895 curproxy->conf.logformat_sd_string = default_rfc5424_sd_log_format;
7896 }
Dragan Dosen1322d092015-09-22 16:05:32 +02007897 break;
Dragan Dosen1322d092015-09-22 16:05:32 +02007898 }
Dragan Dosen1322d092015-09-22 16:05:32 +02007899 }
Dragan Dosen68d2e3a2015-09-19 22:35:44 +02007900
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007901 /* compile the log format */
7902 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02007903 if (curproxy->conf.logformat_string != default_http_log_format &&
7904 curproxy->conf.logformat_string != default_tcp_log_format &&
7905 curproxy->conf.logformat_string != clf_http_log_format)
7906 free(curproxy->conf.logformat_string);
7907 curproxy->conf.logformat_string = NULL;
7908 free(curproxy->conf.lfs_file);
7909 curproxy->conf.lfs_file = NULL;
7910 curproxy->conf.lfs_line = 0;
Dragan Dosen0b85ece2015-09-25 19:17:44 +02007911
7912 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
7913 free(curproxy->conf.logformat_sd_string);
7914 curproxy->conf.logformat_sd_string = NULL;
7915 free(curproxy->conf.lfsd_file);
7916 curproxy->conf.lfsd_file = NULL;
7917 curproxy->conf.lfsd_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007918 }
7919
Willy Tarreau62a61232013-04-12 18:13:46 +02007920 if (curproxy->conf.logformat_string) {
7921 curproxy->conf.args.ctx = ARGC_LOG;
7922 curproxy->conf.args.file = curproxy->conf.lfs_file;
7923 curproxy->conf.args.line = curproxy->conf.lfs_line;
7924 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007925 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007926 curproxy->conf.args.file = NULL;
7927 curproxy->conf.args.line = 0;
7928 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007929
Dragan Dosen0b85ece2015-09-25 19:17:44 +02007930 if (curproxy->conf.logformat_sd_string) {
7931 curproxy->conf.args.ctx = ARGC_LOGSD;
7932 curproxy->conf.args.file = curproxy->conf.lfsd_file;
7933 curproxy->conf.args.line = curproxy->conf.lfsd_line;
7934 parse_logformat_string(curproxy->conf.logformat_sd_string, curproxy, &curproxy->logformat_sd, LOG_OPT_MANDATORY,
7935 SMP_VAL_FE_LOG_END, curproxy->conf.lfsd_file, curproxy->conf.lfsd_line);
7936 add_to_logformat_list(NULL, NULL, LF_SEPARATOR, &curproxy->logformat_sd);
7937 curproxy->conf.args.file = NULL;
7938 curproxy->conf.args.line = 0;
7939 }
7940
Willy Tarreau62a61232013-04-12 18:13:46 +02007941 if (curproxy->conf.uniqueid_format_string) {
7942 curproxy->conf.args.ctx = ARGC_UIF;
7943 curproxy->conf.args.file = curproxy->conf.uif_file;
7944 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01007945 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Godbachd9722032014-12-18 15:44:58 +08007946 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007947 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007948 curproxy->conf.args.file = NULL;
7949 curproxy->conf.args.line = 0;
7950 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007951
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007952 /* only now we can check if some args remain unresolved.
7953 * This must be done after the users and groups resolution.
7954 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007955 cfgerr += smp_resolve_args(curproxy);
7956 if (!cfgerr)
7957 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01007958
Willy Tarreau2738a142006-07-08 17:28:09 +02007959 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007960 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02007961 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02007962 (!curproxy->timeout.connect ||
7963 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007964 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02007965 " | While not properly invalid, you will certainly encounter various problems\n"
7966 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01007967 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007968 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007969 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02007970 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02007971
Willy Tarreau1fa31262007-12-03 00:36:16 +01007972 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
7973 * We must still support older configurations, so let's find out whether those
7974 * parameters have been set or must be copied from contimeouts.
7975 */
7976 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007977 if (!curproxy->timeout.tarpit ||
7978 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007979 /* tarpit timeout not set. We search in the following order:
7980 * default.tarpit, curr.connect, default.connect.
7981 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007982 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007983 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007984 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007985 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007986 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007987 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007988 }
7989 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007990 (!curproxy->timeout.queue ||
7991 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007992 /* queue timeout not set. We search in the following order:
7993 * default.queue, curr.connect, default.connect.
7994 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007995 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007996 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007997 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007998 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007999 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008000 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008001 }
8002 }
8003
Willy Tarreau1620ec32011-08-06 17:05:02 +02008004 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01008005 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
8006 curproxy->check_req = (char *)malloc(curproxy->check_len);
8007 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02008008 }
8009
Willy Tarreau215663d2014-06-13 18:30:23 +02008010 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
8011 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
8012 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
8013 proxy_type_str(curproxy), curproxy->id);
8014 err_code |= ERR_WARN;
8015 }
8016
Willy Tarreau193b8c62012-11-22 00:17:38 +01008017 /* ensure that cookie capture length is not too large */
8018 if (curproxy->capture_len >= global.tune.cookie_len) {
8019 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
8020 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
8021 err_code |= ERR_WARN;
8022 curproxy->capture_len = global.tune.cookie_len - 1;
8023 }
8024
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008025 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01008026 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008027 curproxy->req_cap_pool = create_pool("ptrcap",
8028 curproxy->nb_req_cap * sizeof(char *),
8029 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008030 }
8031
8032 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008033 curproxy->rsp_cap_pool = create_pool("ptrcap",
8034 curproxy->nb_rsp_cap * sizeof(char *),
8035 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008036 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008037
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02008038 switch (curproxy->load_server_state_from_file) {
8039 case PR_SRV_STATE_FILE_UNSPEC:
8040 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
8041 break;
8042 case PR_SRV_STATE_FILE_GLOBAL:
8043 if (!global.server_state_file) {
8044 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",
8045 curproxy->id);
8046 err_code |= ERR_WARN;
8047 }
8048 break;
8049 }
8050
Willy Tarreaubaaee002006-06-26 02:48:02 +02008051 /* first, we will invert the servers list order */
8052 newsrv = NULL;
8053 while (curproxy->srv) {
8054 struct server *next;
8055
8056 next = curproxy->srv->next;
8057 curproxy->srv->next = newsrv;
8058 newsrv = curproxy->srv;
8059 if (!next)
8060 break;
8061 curproxy->srv = next;
8062 }
8063
Willy Tarreau17edc812014-01-03 12:14:34 +01008064 /* Check that no server name conflicts. This causes trouble in the stats.
8065 * We only emit a warning for the first conflict affecting each server,
8066 * in order to avoid combinatory explosion if all servers have the same
8067 * name. We do that only for servers which do not have an explicit ID,
8068 * because these IDs were made also for distinguishing them and we don't
8069 * want to annoy people who correctly manage them.
8070 */
8071 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
8072 struct server *other_srv;
8073
8074 if (newsrv->puid)
8075 continue;
8076
8077 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
8078 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
8079 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
8080 newsrv->conf.file, newsrv->conf.line,
8081 proxy_type_str(curproxy), curproxy->id,
8082 newsrv->id, other_srv->conf.line);
8083 break;
8084 }
8085 }
8086 }
8087
Willy Tarreaudd701652010-05-25 23:03:02 +02008088 /* assign automatic UIDs to servers which don't have one yet */
8089 next_id = 1;
8090 newsrv = curproxy->srv;
8091 while (newsrv != NULL) {
8092 if (!newsrv->puid) {
8093 /* server ID not set, use automatic numbering with first
8094 * spare entry starting with next_svid.
8095 */
8096 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
8097 newsrv->conf.id.key = newsrv->puid = next_id;
8098 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
8099 }
8100 next_id++;
8101 newsrv = newsrv->next;
8102 }
8103
Willy Tarreau20697042007-11-15 23:26:18 +01008104 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01008105 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02008106
Willy Tarreau62c3be22012-01-20 13:12:32 +01008107 /*
8108 * If this server supports a maxconn parameter, it needs a dedicated
8109 * tasks to fill the emptied slots when a connection leaves.
8110 * Also, resolve deferred tracking dependency if needed.
8111 */
8112 newsrv = curproxy->srv;
8113 while (newsrv != NULL) {
8114 if (newsrv->minconn > newsrv->maxconn) {
8115 /* Only 'minconn' was specified, or it was higher than or equal
8116 * to 'maxconn'. Let's turn this into maxconn and clean it, as
8117 * this will avoid further useless expensive computations.
8118 */
8119 newsrv->maxconn = newsrv->minconn;
8120 } else if (newsrv->maxconn && !newsrv->minconn) {
8121 /* minconn was not specified, so we set it to maxconn */
8122 newsrv->minconn = newsrv->maxconn;
8123 }
8124
Emeric Brun01f8e2f2012-05-18 16:02:00 +02008125#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02008126 if (newsrv->use_ssl || newsrv->check.use_ssl)
8127 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02008128#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02008129
Willy Tarreau2f075e92013-12-03 11:11:34 +01008130 /* set the check type on the server */
8131 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
8132
Willy Tarreau62c3be22012-01-20 13:12:32 +01008133 if (newsrv->trackit) {
8134 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02008135 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008136 char *pname, *sname;
8137
8138 pname = newsrv->trackit;
8139 sname = strrchr(pname, '/');
8140
8141 if (sname)
8142 *sname++ = '\0';
8143 else {
8144 sname = pname;
8145 pname = NULL;
8146 }
8147
8148 if (pname) {
Willy Tarreau9e0bb102015-05-26 11:24:42 +02008149 px = proxy_be_by_name(pname);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008150 if (!px) {
8151 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
8152 proxy_type_str(curproxy), curproxy->id,
8153 newsrv->id, pname);
8154 cfgerr++;
8155 goto next_srv;
8156 }
8157 } else
8158 px = curproxy;
8159
8160 srv = findserver(px, sname);
8161 if (!srv) {
8162 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
8163 proxy_type_str(curproxy), curproxy->id,
8164 newsrv->id, sname);
8165 cfgerr++;
8166 goto next_srv;
8167 }
8168
Willy Tarreau32091232014-05-16 13:52:00 +02008169 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
8170 !(srv->agent.state & CHK_ST_CONFIGURED) &&
8171 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01008172 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02008173 "tracking as it does not have any check nor agent enabled.\n",
8174 proxy_type_str(curproxy), curproxy->id,
8175 newsrv->id, px->id, srv->id);
8176 cfgerr++;
8177 goto next_srv;
8178 }
8179
8180 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
8181
8182 if (loop) {
8183 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
8184 "belongs to a tracking chain looping back to %s/%s.\n",
8185 proxy_type_str(curproxy), curproxy->id,
8186 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008187 cfgerr++;
8188 goto next_srv;
8189 }
8190
8191 if (curproxy != px &&
8192 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
8193 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
8194 "tracking: disable-on-404 option inconsistency.\n",
8195 proxy_type_str(curproxy), curproxy->id,
8196 newsrv->id, px->id, srv->id);
8197 cfgerr++;
8198 goto next_srv;
8199 }
8200
8201 /* if the other server is forced disabled, we have to do the same here */
Willy Tarreau20125212014-05-13 19:44:56 +02008202 if (srv->admin & SRV_ADMF_MAINT) {
Willy Tarreaua0066dd2014-05-16 11:25:16 +02008203 newsrv->admin |= SRV_ADMF_IMAINT;
Willy Tarreau892337c2014-05-13 23:41:20 +02008204 newsrv->state = SRV_ST_STOPPED;
Simon Horman125d0992013-02-24 17:23:38 +09008205 newsrv->check.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008206 }
8207
8208 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01008209 newsrv->tracknext = srv->trackers;
8210 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008211
8212 free(newsrv->trackit);
8213 newsrv->trackit = NULL;
8214 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008215
8216 /*
8217 * resolve server's resolvers name and update the resolvers pointer
8218 * accordingly
8219 */
8220 if (newsrv->resolvers_id) {
8221 struct dns_resolvers *curr_resolvers;
8222 int found;
8223
8224 found = 0;
8225 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
8226 if (!strcmp(curr_resolvers->id, newsrv->resolvers_id)) {
8227 found = 1;
8228 break;
8229 }
8230 }
8231
8232 if (!found) {
8233 Alert("config : %s '%s', server '%s': unable to find required resolvers '%s'\n",
8234 proxy_type_str(curproxy), curproxy->id,
8235 newsrv->id, newsrv->resolvers_id);
8236 cfgerr++;
8237 } else {
8238 free(newsrv->resolvers_id);
8239 newsrv->resolvers_id = NULL;
8240 if (newsrv->resolution)
8241 newsrv->resolution->resolvers = curr_resolvers;
8242 }
8243 }
8244 else {
8245 /* if no resolvers section associated to this server
8246 * we can clean up the associated resolution structure
8247 */
8248 if (newsrv->resolution) {
8249 free(newsrv->resolution->hostname_dn);
8250 newsrv->resolution->hostname_dn = NULL;
8251 free(newsrv->resolution);
8252 newsrv->resolution = NULL;
8253 }
8254 }
8255
Willy Tarreau62c3be22012-01-20 13:12:32 +01008256 next_srv:
8257 newsrv = newsrv->next;
8258 }
8259
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008260 /* We have to initialize the server lookup mechanism depending
8261 * on what LB algorithm was choosen.
8262 */
8263
8264 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
8265 switch (curproxy->lbprm.algo & BE_LB_KIND) {
8266 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02008267 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
8268 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8269 init_server_map(curproxy);
8270 } else {
8271 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
8272 fwrr_init_server_groups(curproxy);
8273 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008274 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008275
Willy Tarreau3ebb1162012-02-13 16:57:44 +01008276 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01008277 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
8278 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
8279 fwlc_init_server_tree(curproxy);
8280 } else {
8281 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
8282 fas_init_server_tree(curproxy);
8283 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008284 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008285
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008286 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008287 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
8288 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
8289 chash_init_server_tree(curproxy);
8290 } else {
8291 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8292 init_server_map(curproxy);
8293 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008294 break;
8295 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02008296
8297 if (curproxy->options & PR_O_LOGASAP)
8298 curproxy->to_log &= ~LW_BYTES;
8299
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008300 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008301 (curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->logsrvs) &&
8302 (!LIST_ISEMPTY(&curproxy->logformat) || !LIST_ISEMPTY(&curproxy->logformat_sd))) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008303 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
8304 proxy_type_str(curproxy), curproxy->id);
8305 err_code |= ERR_WARN;
8306 }
8307
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008308 if (curproxy->mode != PR_MODE_HTTP) {
8309 int optnum;
8310
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008311 if (curproxy->uri_auth) {
8312 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
8313 proxy_type_str(curproxy), curproxy->id);
8314 err_code |= ERR_WARN;
8315 curproxy->uri_auth = NULL;
8316 }
8317
Willy Tarreau87cf5142011-08-19 22:57:24 +02008318 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008319 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8320 "forwardfor", proxy_type_str(curproxy), curproxy->id);
8321 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02008322 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008323 }
8324
8325 if (curproxy->options & PR_O_ORGTO) {
8326 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8327 "originalto", proxy_type_str(curproxy), curproxy->id);
8328 err_code |= ERR_WARN;
8329 curproxy->options &= ~PR_O_ORGTO;
8330 }
8331
8332 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
8333 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
8334 (curproxy->cap & cfg_opts[optnum].cap) &&
8335 (curproxy->options & cfg_opts[optnum].val)) {
8336 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8337 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
8338 err_code |= ERR_WARN;
8339 curproxy->options &= ~cfg_opts[optnum].val;
8340 }
8341 }
8342
8343 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
8344 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
8345 (curproxy->cap & cfg_opts2[optnum].cap) &&
8346 (curproxy->options2 & cfg_opts2[optnum].val)) {
8347 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8348 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
8349 err_code |= ERR_WARN;
8350 curproxy->options2 &= ~cfg_opts2[optnum].val;
8351 }
8352 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008353
Willy Tarreau29fbe512015-08-20 19:35:14 +02008354#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008355 if (curproxy->conn_src.bind_hdr_occ) {
8356 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008357 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01008358 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008359 err_code |= ERR_WARN;
8360 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008361#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008362 }
8363
Willy Tarreaubaaee002006-06-26 02:48:02 +02008364 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01008365 * ensure that we're not cross-dressing a TCP server into HTTP.
8366 */
8367 newsrv = curproxy->srv;
8368 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01008369 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008370 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
8371 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008372 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01008373 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008374
Willy Tarreau0cec3312011-10-31 13:49:26 +01008375 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
8376 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
8377 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8378 err_code |= ERR_WARN;
8379 }
8380
Willy Tarreauc93cd162014-05-13 15:54:22 +02008381 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02008382 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
8383 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8384 err_code |= ERR_WARN;
8385 }
8386
Willy Tarreau29fbe512015-08-20 19:35:14 +02008387#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008388 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
8389 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008390 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 +01008391 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008392 err_code |= ERR_WARN;
8393 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008394#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01008395 newsrv = newsrv->next;
8396 }
8397
Willy Tarreaue42bd962014-09-16 16:21:19 +02008398 /* check if we have a frontend with "tcp-request content" looking at L7
8399 * with no inspect-delay
8400 */
8401 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
8402 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008403 if (trule->action == ACT_TCP_CAPTURE &&
Thierry FOURNIERd0d65ae2015-08-04 08:21:12 +02008404 !(trule->arg.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008405 break;
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008406 if ((trule->action >= ACT_ACTION_TRK_SC0 && trule->action <= ACT_ACTION_TRK_SCMAX) &&
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008407 !(trule->arg.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008408 break;
8409 }
8410
8411 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
8412 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
8413 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
8414 " This means that these rules will randomly find their contents. This can be fixed by"
8415 " setting the tcp-request inspect-delay.\n",
8416 proxy_type_str(curproxy), curproxy->id);
8417 err_code |= ERR_WARN;
8418 }
8419 }
8420
Willy Tarreauc1a21672009-08-16 22:37:44 +02008421 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02008422 if (!curproxy->accept)
8423 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02008424
Willy Tarreauc1a21672009-08-16 22:37:44 +02008425 if (curproxy->tcp_req.inspect_delay ||
8426 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02008427 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008428
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008429 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008430 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008431 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008432 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008433
8434 /* both TCP and HTTP must check switching rules */
8435 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
8436 }
8437
8438 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02008439 if (curproxy->tcp_req.inspect_delay ||
8440 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
8441 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
8442
Emeric Brun97679e72010-09-23 17:56:44 +02008443 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
8444 curproxy->be_rsp_ana |= AN_RES_INSPECT;
8445
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008446 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008447 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008448 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008449 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008450
8451 /* If the backend does requires RDP cookie persistence, we have to
8452 * enable the corresponding analyser.
8453 */
8454 if (curproxy->options2 & PR_O2_RDPC_PRST)
8455 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
8456 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008457 }
8458
8459 /***********************************************************/
8460 /* At this point, target names have already been resolved. */
8461 /***********************************************************/
8462
8463 /* Check multi-process mode compatibility */
8464
8465 if (global.nbproc > 1 && global.stats_fe) {
8466 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8467 unsigned long mask;
8468
8469 mask = nbits(global.nbproc);
8470 if (global.stats_fe->bind_proc)
8471 mask &= global.stats_fe->bind_proc;
8472
8473 if (bind_conf->bind_proc)
8474 mask &= bind_conf->bind_proc;
8475
8476 /* stop here if more than one process is used */
David Carliere6c39412015-07-02 07:00:17 +00008477 if (my_popcountl(mask) > 1)
Willy Tarreau419ead82014-09-16 13:41:21 +02008478 break;
8479 }
8480 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
8481 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");
8482 }
8483 }
8484
8485 /* Make each frontend inherit bind-process from its listeners when not specified. */
8486 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8487 if (curproxy->bind_proc)
8488 continue;
8489
8490 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8491 unsigned long mask;
8492
Willy Tarreaue428b082015-05-04 21:57:58 +02008493 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008494 curproxy->bind_proc |= mask;
8495 }
8496
8497 if (!curproxy->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008498 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008499 }
8500
8501 if (global.stats_fe) {
8502 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8503 unsigned long mask;
8504
Willy Tarreaue428b082015-05-04 21:57:58 +02008505 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008506 global.stats_fe->bind_proc |= mask;
8507 }
8508 if (!global.stats_fe->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008509 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008510 }
8511
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02008512 /* propagate bindings from frontends to backends. Don't do it if there
8513 * are any fatal errors as we must not call it with unresolved proxies.
8514 */
8515 if (!cfgerr) {
8516 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8517 if (curproxy->cap & PR_CAP_FE)
8518 propagate_processes(curproxy, NULL);
8519 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008520 }
8521
8522 /* Bind each unbound backend to all processes when not specified. */
8523 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8524 if (curproxy->bind_proc)
8525 continue;
Willy Tarreaue428b082015-05-04 21:57:58 +02008526 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008527 }
8528
8529 /*******************************************************/
8530 /* At this step, all proxies have a non-null bind_proc */
8531 /*******************************************************/
8532
8533 /* perform the final checks before creating tasks */
8534
8535 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8536 struct listener *listener;
8537 unsigned int next_id;
8538 int nbproc;
8539
David Carliere6c39412015-07-02 07:00:17 +00008540 nbproc = my_popcountl(curproxy->bind_proc & nbits(global.nbproc));
Willy Tarreauc1a21672009-08-16 22:37:44 +02008541
Emeric Brunc52962f2012-11-15 18:28:02 +01008542#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008543 /* Configure SSL for each bind line.
8544 * Note: if configuration fails at some point, the ->ctx member
8545 * remains NULL so that listeners can later detach.
8546 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008547 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008548 int alloc_ctx;
8549
Emeric Brunc52962f2012-11-15 18:28:02 +01008550 if (!bind_conf->is_ssl) {
8551 if (bind_conf->default_ctx) {
8552 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
8553 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
8554 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008555 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01008556 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008557 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02008558 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008559 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008560 cfgerr++;
8561 continue;
8562 }
8563
Emeric Brun8dc60392014-05-09 13:52:00 +02008564 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008565 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02008566 if (alloc_ctx == SHCTX_E_INIT_LOCK)
8567 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");
8568 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008569 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02008570 cfgerr++;
8571 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008572 }
8573
Emeric Brunfc0421f2012-09-07 17:30:07 +02008574 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008575 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008576
8577 /* initialize CA variables if the certificates generation is enabled */
8578 cfgerr += ssl_sock_load_ca(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008579 }
Emeric Brunc52962f2012-11-15 18:28:02 +01008580#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008581
Willy Tarreaue6b98942007-10-29 01:09:36 +01008582 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008583 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008584 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008585 if (!listener->luid) {
8586 /* listener ID not set, use automatic numbering with first
8587 * spare entry starting with next_luid.
8588 */
8589 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
8590 listener->conf.id.key = listener->luid = next_id;
8591 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008592 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01008593 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008594
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008595 /* enable separate counters */
8596 if (curproxy->options2 & PR_O2_SOCKSTAT) {
8597 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01008598 if (!listener->name)
8599 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008600 }
Willy Tarreau81796be2012-09-22 19:11:47 +02008601
Willy Tarreaue6b98942007-10-29 01:09:36 +01008602 if (curproxy->options & PR_O_TCP_NOLING)
8603 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02008604 if (!listener->maxconn)
8605 listener->maxconn = curproxy->maxconn;
8606 if (!listener->backlog)
8607 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01008608 if (!listener->maxaccept)
8609 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
8610
8611 /* we want to have an optimal behaviour on single process mode to
8612 * maximize the work at once, but in multi-process we want to keep
8613 * some fairness between processes, so we target half of the max
8614 * number of events to be balanced over all the processes the proxy
8615 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
8616 * used to disable the limit.
8617 */
8618 if (listener->maxaccept > 0) {
8619 if (nbproc > 1)
8620 listener->maxaccept = (listener->maxaccept + 1) / 2;
8621 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
8622 }
8623
Willy Tarreau9903f0e2015-04-04 18:50:31 +02008624 listener->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02008625 listener->handler = process_stream;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008626 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01008627 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01008628
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008629 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
8630 listener->options |= LI_O_TCP_RULES;
8631
Willy Tarreaude3041d2010-05-31 10:56:17 +02008632 if (curproxy->mon_mask.s_addr)
8633 listener->options |= LI_O_CHK_MONNET;
8634
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008635 /* smart accept mode is automatic in HTTP mode */
8636 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008637 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008638 !(curproxy->no_options2 & PR_O2_SMARTACC)))
8639 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01008640 }
8641
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008642 /* Release unused SSL configs */
8643 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8644 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008645 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008646#ifdef USE_OPENSSL
Christopher Faulet31af49d2015-06-09 17:29:50 +02008647 ssl_sock_free_ca(bind_conf);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008648 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008649 free(bind_conf->ca_file);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008650 free(bind_conf->ca_sign_file);
8651 free(bind_conf->ca_sign_pass);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008652 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02008653 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008654 free(bind_conf->crl_file);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008655 if(bind_conf->keys_ref) {
8656 free(bind_conf->keys_ref->filename);
8657 free(bind_conf->keys_ref->tlskeys);
8658 free(bind_conf->keys_ref);
8659 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008660#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008661 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008662
Willy Tarreau102df612014-05-07 23:56:38 +02008663 if (nbproc > 1) {
8664 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02008665 int count, maxproc = 0;
8666
8667 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
David Carliere6c39412015-07-02 07:00:17 +00008668 count = my_popcountl(bind_conf->bind_proc);
Willy Tarreaueb791e02014-09-16 15:11:04 +02008669 if (count > maxproc)
8670 maxproc = count;
8671 }
8672 /* backends have 0, frontends have 1 or more */
8673 if (maxproc != 1)
8674 Warning("Proxy '%s': in multi-process mode, stats will be"
8675 " limited to process assigned to the current request.\n",
8676 curproxy->id);
8677
Willy Tarreau102df612014-05-07 23:56:38 +02008678 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
8679 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
8680 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008681 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008682 }
Willy Tarreau102df612014-05-07 23:56:38 +02008683 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
8684 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
8685 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008686 }
8687 }
Willy Tarreau918ff602011-07-25 16:33:49 +02008688
8689 /* create the task associated with the proxy */
8690 curproxy->task = task_new();
8691 if (curproxy->task) {
8692 curproxy->task->context = curproxy;
8693 curproxy->task->process = manage_proxy;
8694 /* no need to queue, it will be done automatically if some
8695 * listener gets limited.
8696 */
8697 curproxy->task->expire = TICK_ETERNITY;
8698 } else {
8699 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
8700 curproxy->id);
8701 cfgerr++;
8702 }
Willy Tarreaub369a042014-09-16 13:21:03 +02008703 }
8704
Willy Tarreaufbb78422011-06-05 15:38:35 +02008705 /* automatically compute fullconn if not set. We must not do it in the
8706 * loop above because cross-references are not yet fully resolved.
8707 */
8708 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8709 /* If <fullconn> is not set, let's set it to 10% of the sum of
8710 * the possible incoming frontend's maxconns.
8711 */
8712 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
8713 struct proxy *fe;
8714 int total = 0;
8715
8716 /* sum up the number of maxconns of frontends which
8717 * reference this backend at least once or which are
8718 * the same one ('listen').
8719 */
8720 for (fe = proxy; fe; fe = fe->next) {
8721 struct switching_rule *rule;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008722 int found = 0;
8723
8724 if (!(fe->cap & PR_CAP_FE))
8725 continue;
8726
8727 if (fe == curproxy) /* we're on a "listen" instance */
8728 found = 1;
8729
8730 if (fe->defbe.be == curproxy) /* "default_backend" */
8731 found = 1;
8732
8733 /* check if a "use_backend" rule matches */
8734 if (!found) {
8735 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01008736 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02008737 found = 1;
8738 break;
8739 }
8740 }
8741 }
8742
Willy Tarreaufbb78422011-06-05 15:38:35 +02008743 /* now we've checked all possible ways to reference a backend
8744 * from a frontend.
8745 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02008746 if (!found)
8747 continue;
8748 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008749 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02008750 /* we have the sum of the maxconns in <total>. We only
8751 * keep 10% of that sum to set the default fullconn, with
8752 * a hard minimum of 1 (to avoid a divide by zero).
8753 */
8754 curproxy->fullconn = (total + 9) / 10;
8755 if (!curproxy->fullconn)
8756 curproxy->fullconn = 1;
8757 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01008758 }
8759
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008760 /*
8761 * Recount currently required checks.
8762 */
8763
8764 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
8765 int optnum;
8766
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008767 for (optnum = 0; cfg_opts[optnum].name; optnum++)
8768 if (curproxy->options & cfg_opts[optnum].val)
8769 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008770
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008771 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
8772 if (curproxy->options2 & cfg_opts2[optnum].val)
8773 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008774 }
8775
Willy Tarreau0fca4832015-05-01 19:12:05 +02008776 /* compute the required process bindings for the peers */
8777 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
8778 if (curproxy->table.peers.p)
8779 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
8780
Willy Tarreau122541c2011-09-07 21:24:49 +02008781 if (peers) {
8782 struct peers *curpeers = peers, **last;
8783 struct peer *p, *pb;
8784
Willy Tarreau1e273012015-05-01 19:15:17 +02008785 /* Remove all peers sections which don't have a valid listener,
8786 * which are not used by any table, or which are bound to more
8787 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02008788 */
8789 last = &peers;
8790 while (*last) {
8791 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008792
8793 if (curpeers->state == PR_STSTOPPED) {
8794 /* the "disabled" keyword was present */
8795 if (curpeers->peers_fe)
8796 stop_proxy(curpeers->peers_fe);
8797 curpeers->peers_fe = NULL;
8798 }
8799 else if (!curpeers->peers_fe) {
8800 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
8801 curpeers->id, localpeer);
8802 }
David Carliere6c39412015-07-02 07:00:17 +00008803 else if (my_popcountl(curpeers->peers_fe->bind_proc) != 1) {
Willy Tarreau1e273012015-05-01 19:15:17 +02008804 /* either it's totally stopped or too much used */
8805 if (curpeers->peers_fe->bind_proc) {
8806 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreau64c57222015-05-04 21:48:51 +02008807 "running in different processes (%d different ones). "
8808 "Check global.nbproc and all tables' bind-process "
David Carliere6c39412015-07-02 07:00:17 +00008809 "settings.\n", curpeers->id, my_popcountl(curpeers->peers_fe->bind_proc));
Willy Tarreau1e273012015-05-01 19:15:17 +02008810 cfgerr++;
8811 }
8812 stop_proxy(curpeers->peers_fe);
8813 curpeers->peers_fe = NULL;
8814 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008815 else {
Emeric Brunb3971ab2015-05-12 18:49:09 +02008816 peers_init_sync(curpeers);
Willy Tarreau122541c2011-09-07 21:24:49 +02008817 last = &curpeers->next;
8818 continue;
8819 }
8820
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008821 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02008822 p = curpeers->remote;
8823 while (p) {
8824 pb = p->next;
8825 free(p->id);
8826 free(p);
8827 p = pb;
8828 }
8829
8830 /* Destroy and unlink this curpeers section.
8831 * Note: curpeers is backed up into *last.
8832 */
8833 free(curpeers->id);
8834 curpeers = curpeers->next;
8835 free(*last);
8836 *last = curpeers;
8837 }
8838 }
8839
Willy Tarreau6866f3f2015-05-01 19:09:08 +02008840 /* initialize stick-tables on backend capable proxies. This must not
8841 * be done earlier because the data size may be discovered while parsing
8842 * other proxies.
8843 */
8844 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8845 if (curproxy->state == PR_STSTOPPED)
8846 continue;
8847
8848 if (!stktable_init(&curproxy->table)) {
8849 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
8850 cfgerr++;
8851 }
8852 }
8853
Simon Horman0d16a402015-01-30 11:22:58 +09008854 if (mailers) {
8855 struct mailers *curmailers = mailers, **last;
8856 struct mailer *m, *mb;
8857
8858 /* Remove all mailers sections which don't have a valid listener.
8859 * This can happen when a mailers section is never referenced.
8860 */
8861 last = &mailers;
8862 while (*last) {
8863 curmailers = *last;
8864 if (curmailers->users) {
8865 last = &curmailers->next;
8866 continue;
8867 }
8868
8869 Warning("Removing incomplete section 'mailers %s'.\n",
8870 curmailers->id);
8871
8872 m = curmailers->mailer_list;
8873 while (m) {
8874 mb = m->next;
8875 free(m->id);
8876 free(m);
8877 m = mb;
8878 }
8879
8880 /* Destroy and unlink this curmailers section.
8881 * Note: curmailers is backed up into *last.
8882 */
8883 free(curmailers->id);
8884 curmailers = curmailers->next;
8885 free(*last);
8886 *last = curmailers;
8887 }
8888 }
8889
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02008890 /* Update server_state_file_name to backend name if backend is supposed to use
8891 * a server-state file locally defined and none has been provided */
8892 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8893 if (curproxy->load_server_state_from_file == PR_SRV_STATE_FILE_LOCAL &&
8894 curproxy->server_state_file_name == NULL)
8895 curproxy->server_state_file_name = strdup(curproxy->id);
8896 }
8897
Willy Tarreau34eb6712011-10-24 18:15:04 +02008898 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02008899 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02008900 MEM_F_SHARED);
8901
Willy Tarreaubb925012009-07-23 13:36:36 +02008902 if (cfgerr > 0)
8903 err_code |= ERR_ALERT | ERR_FATAL;
8904 out:
8905 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02008906}
8907
Willy Tarreau5b2c3362008-07-09 19:39:06 +02008908/*
8909 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
8910 * parsing sessions.
8911 */
8912void cfg_register_keywords(struct cfg_kw_list *kwl)
8913{
8914 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
8915}
Willy Tarreaubaaee002006-06-26 02:48:02 +02008916
Willy Tarreau5b2c3362008-07-09 19:39:06 +02008917/*
8918 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
8919 */
8920void cfg_unregister_keywords(struct cfg_kw_list *kwl)
8921{
8922 LIST_DEL(&kwl->list);
8923 LIST_INIT(&kwl->list);
8924}
Willy Tarreaubaaee002006-06-26 02:48:02 +02008925
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01008926/* this function register new section in the haproxy configuration file.
8927 * <section_name> is the name of this new section and <section_parser>
8928 * is the called parser. If two section declaration have the same name,
8929 * only the first declared is used.
8930 */
8931int cfg_register_section(char *section_name,
8932 int (*section_parser)(const char *, int, char **, int))
8933{
8934 struct cfg_section *cs;
8935
8936 cs = calloc(1, sizeof(*cs));
8937 if (!cs) {
8938 Alert("register section '%s': out of memory.\n", section_name);
8939 return 0;
8940 }
8941
8942 cs->section_name = section_name;
8943 cs->section_parser = section_parser;
8944
8945 LIST_ADDQ(&sections, &cs->list);
8946
8947 return 1;
8948}
8949
Willy Tarreaubaaee002006-06-26 02:48:02 +02008950/*
David Carlier845efb52015-09-25 11:49:18 +01008951 * free all config section entries
8952 */
8953void cfg_unregister_sections(void)
8954{
8955 struct cfg_section *cs, *ics;
8956
8957 list_for_each_entry_safe(cs, ics, &sections, list) {
8958 LIST_DEL(&cs->list);
8959 free(cs);
8960 }
8961}
8962
8963/*
Willy Tarreaubaaee002006-06-26 02:48:02 +02008964 * Local variables:
8965 * c-indent-level: 8
8966 * c-basic-offset: 8
8967 * End:
8968 */