blob: 6958a1d24ab5c22b4e4d692ae9047ac4383cd0aa [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 /* We'll add a space after the name to respect the log format */
1663 free(global.log_send_hostname);
Dragan Dosenc8cfa7b2015-09-28 13:28:21 +02001664 global.log_send_hostname = strdup(name);
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001665 }
Baptiste Assmann6bc89362015-08-23 09:22:25 +02001666 else if (!strcmp(args[0], "server-state-base")) { /* path base where HAProxy can find server state files */
1667 if (global.server_state_base != NULL) {
1668 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1669 err_code |= ERR_ALERT;
1670 goto out;
1671 }
1672
1673 if (!*(args[1])) {
1674 Alert("parsing [%s:%d] : '%s' expects one argument: a directory path.\n", file, linenum, args[0]);
1675 err_code |= ERR_FATAL;
1676 goto out;
1677 }
1678
1679 global.server_state_base = strdup(args[1]);
1680 }
Baptiste Assmanne0882262015-08-23 09:54:31 +02001681 else if (!strcmp(args[0], "server-state-file")) { /* path to the file where HAProxy can load the server states */
1682 if (global.server_state_file != NULL) {
1683 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1684 err_code |= ERR_ALERT;
1685 goto out;
1686 }
1687
1688 if (!*(args[1])) {
1689 Alert("parsing [%s:%d] : '%s' expect one argument: a file path.\n", file, linenum, args[0]);
1690 err_code |= ERR_FATAL;
1691 goto out;
1692 }
1693
1694 global.server_state_file = strdup(args[1]);
1695 }
Kevinm48936af2010-12-22 16:08:21 +00001696 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
William Lallemand1a748ae2015-05-19 16:37:23 +02001697 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1698 goto out;
Kevinm48936af2010-12-22 16:08:21 +00001699 if (*(args[1]) == 0) {
1700 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1701 err_code |= ERR_ALERT | ERR_FATAL;
1702 goto out;
1703 }
1704 free(global.log_tag);
1705 global.log_tag = strdup(args[1]);
1706 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001707 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
William Lallemand1a748ae2015-05-19 16:37:23 +02001708 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1709 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001710 if (global.spread_checks != 0) {
1711 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001712 err_code |= ERR_ALERT;
1713 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001714 }
1715 if (*(args[1]) == 0) {
1716 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001717 err_code |= ERR_ALERT | ERR_FATAL;
1718 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001719 }
1720 global.spread_checks = atol(args[1]);
1721 if (global.spread_checks < 0 || global.spread_checks > 50) {
1722 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001723 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001724 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001725 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001726 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1727 const char *err;
1728 unsigned int val;
1729
William Lallemand1a748ae2015-05-19 16:37:23 +02001730 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1731 goto out;
Willy Tarreau1746eec2014-04-25 10:46:47 +02001732 if (*(args[1]) == 0) {
1733 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1734 err_code |= ERR_ALERT | ERR_FATAL;
1735 goto out;
1736 }
1737
1738 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1739 if (err) {
1740 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1741 err_code |= ERR_ALERT | ERR_FATAL;
1742 }
1743 global.max_spread_checks = val;
1744 if (global.max_spread_checks < 0) {
1745 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1746 err_code |= ERR_ALERT | ERR_FATAL;
1747 }
1748 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001749 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1750#ifdef USE_CPU_AFFINITY
1751 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001752 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001753 unsigned long cpus = 0;
1754
1755 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001756 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001757 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001758 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001759 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001760 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001761 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001762 proc = atol(args[1]);
1763 if (proc >= 1 && proc <= LONGBITS)
1764 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001765 }
1766
1767 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001768 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",
1769 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001770 err_code |= ERR_ALERT | ERR_FATAL;
1771 goto out;
1772 }
1773
1774 cur_arg = 2;
1775 while (*args[cur_arg]) {
1776 unsigned int low, high;
1777
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001778 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001779 char *dash = strchr(args[cur_arg], '-');
1780
1781 low = high = str2uic(args[cur_arg]);
1782 if (dash)
1783 high = str2uic(dash + 1);
1784
1785 if (high < low) {
1786 unsigned int swap = low;
1787 low = high;
1788 high = swap;
1789 }
1790
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001791 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001792 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001793 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001794 err_code |= ERR_ALERT | ERR_FATAL;
1795 goto out;
1796 }
1797
1798 while (low <= high)
1799 cpus |= 1UL << low++;
1800 }
1801 else {
1802 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1803 file, linenum, args[0], args[cur_arg]);
1804 err_code |= ERR_ALERT | ERR_FATAL;
1805 goto out;
1806 }
1807 cur_arg++;
1808 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001809 for (i = 0; i < LONGBITS; i++)
1810 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001811 global.cpu_map[i] = cpus;
1812#else
1813 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1814 err_code |= ERR_ALERT | ERR_FATAL;
1815 goto out;
1816#endif
1817 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001818 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001819 struct cfg_kw_list *kwl;
1820 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001821 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001822
1823 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1824 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1825 if (kwl->kw[index].section != CFG_GLOBAL)
1826 continue;
1827 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001828 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001829 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001830 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001831 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001832 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001833 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001834 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001835 err_code |= ERR_WARN;
1836 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001837 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001838 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001839 }
1840 }
1841 }
1842
Willy Tarreaubaaee002006-06-26 02:48:02 +02001843 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001844 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001845 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001846
Willy Tarreau058e9072009-07-20 09:30:05 +02001847 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001848 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001849 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001850}
1851
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001852void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001853{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001854 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001855 defproxy.mode = PR_MODE_TCP;
1856 defproxy.state = PR_STNEW;
1857 defproxy.maxconn = cfg_maxpconn;
1858 defproxy.conn_retries = CONN_RETRIES;
Joseph Lynch726ab712015-05-11 23:25:34 -07001859 defproxy.redispatch_after = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001860
Simon Horman66183002013-02-23 10:16:43 +09001861 defproxy.defsrv.check.inter = DEF_CHKINTR;
1862 defproxy.defsrv.check.fastinter = 0;
1863 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001864 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1865 defproxy.defsrv.agent.fastinter = 0;
1866 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001867 defproxy.defsrv.check.rise = DEF_RISETIME;
1868 defproxy.defsrv.check.fall = DEF_FALLTIME;
1869 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1870 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001871 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001872 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001873 defproxy.defsrv.maxqueue = 0;
1874 defproxy.defsrv.minconn = 0;
1875 defproxy.defsrv.maxconn = 0;
1876 defproxy.defsrv.slowstart = 0;
1877 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1878 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1879 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Simon Horman64e34162015-02-06 11:11:57 +09001880
1881 defproxy.email_alert.level = LOG_ALERT;
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02001882 defproxy.load_server_state_from_file = PR_SRV_STATE_FILE_UNSPEC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001883}
1884
Willy Tarreauade5ec42010-01-28 19:33:49 +01001885
Willy Tarreau63af98d2014-05-18 08:11:41 +02001886/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1887 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1888 * ERR_FATAL in case of error.
1889 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001890static int create_cond_regex_rule(const char *file, int line,
1891 struct proxy *px, int dir, int action, int flags,
1892 const char *cmd, const char *reg, const char *repl,
1893 const char **cond_start)
1894{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001895 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001896 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001897 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001898 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001899 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001900 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001901 int cs;
1902 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001903
1904 if (px == &defproxy) {
1905 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001906 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001907 goto err;
1908 }
1909
1910 if (*reg == 0) {
1911 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001912 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001913 goto err;
1914 }
1915
1916 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001917 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001918
Willy Tarreau5321c422010-01-28 20:35:13 +01001919 if (cond_start &&
1920 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001921 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1922 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1923 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001924 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001925 goto err;
1926 }
1927 }
1928 else if (cond_start && **cond_start) {
1929 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1930 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001931 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001932 goto err;
1933 }
1934
Willy Tarreau63af98d2014-05-18 08:11:41 +02001935 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001936 (dir == SMP_OPT_DIR_REQ) ?
1937 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1938 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1939 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001940
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001941 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001942 if (!preg) {
1943 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001944 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001945 goto err;
1946 }
1947
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001948 cs = !(flags & REG_ICASE);
1949 cap = !(flags & REG_NOSUB);
1950 error = NULL;
1951 if (!regex_comp(reg, preg, cs, cap, &error)) {
1952 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1953 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001954 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001955 goto err;
1956 }
1957
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001958 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001959 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001960 if (repl && err) {
1961 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1962 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001963 ret_code |= ERR_ALERT | ERR_FATAL;
1964 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001965 }
1966
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001967 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001968 ret_code |= ERR_WARN;
1969
1970 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001971
Willy Tarreau63af98d2014-05-18 08:11:41 +02001972 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001973 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001974 err:
1975 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001976 free(errmsg);
1977 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001978}
1979
Willy Tarreaubaaee002006-06-26 02:48:02 +02001980/*
William Lallemand51097192015-04-14 16:35:22 +02001981 * Parse a line in a <listen>, <frontend> or <backend> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001982 * Returns the error code, 0 if OK, or any combination of :
1983 * - ERR_ABORT: must abort ASAP
1984 * - ERR_FATAL: we can continue parsing but not start the service
1985 * - ERR_WARN: a warning has been emitted
1986 * - ERR_ALERT: an alert has been emitted
1987 * Only the two first ones can stop processing, the two others are just
1988 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001989 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001990int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1991{
1992 static struct peers *curpeers = NULL;
1993 struct peer *newpeer = NULL;
1994 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001995 struct bind_conf *bind_conf;
1996 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001997 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001998 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001999
2000 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002001 if (!*args[1]) {
2002 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01002003 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002004 goto out;
2005 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002006
William Lallemand6e62fb62015-04-28 16:55:23 +02002007 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2008 goto out;
2009
Emeric Brun32da3c42010-09-23 18:39:19 +02002010 err = invalid_char(args[1]);
2011 if (err) {
2012 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2013 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01002014 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002015 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002016 }
2017
2018 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
2019 /*
2020 * If there are two proxies with the same name only following
2021 * combinations are allowed:
2022 */
2023 if (strcmp(curpeers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002024 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 +02002025 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002026 err_code |= ERR_ALERT | ERR_FATAL;
Emeric Brun32da3c42010-09-23 18:39:19 +02002027 }
2028 }
2029
2030 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
2031 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2032 err_code |= ERR_ALERT | ERR_ABORT;
2033 goto out;
2034 }
2035
2036 curpeers->next = peers;
2037 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002038 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002039 curpeers->conf.line = linenum;
2040 curpeers->last_change = now.tv_sec;
2041 curpeers->id = strdup(args[1]);
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002042 curpeers->state = PR_STNEW;
Emeric Brun32da3c42010-09-23 18:39:19 +02002043 }
2044 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01002045 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01002046 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002047 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02002048
2049 if (!*args[2]) {
2050 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2051 file, linenum, args[0]);
2052 err_code |= ERR_ALERT | ERR_FATAL;
2053 goto out;
2054 }
2055
2056 err = invalid_char(args[1]);
2057 if (err) {
2058 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2059 file, linenum, *err, args[1]);
2060 err_code |= ERR_ALERT | ERR_FATAL;
2061 goto out;
2062 }
2063
2064 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
2065 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2066 err_code |= ERR_ALERT | ERR_ABORT;
2067 goto out;
2068 }
2069
2070 /* the peers are linked backwards first */
2071 curpeers->count++;
2072 newpeer->next = curpeers->remote;
2073 curpeers->remote = newpeer;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002074 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002075 newpeer->conf.line = linenum;
2076
2077 newpeer->last_change = now.tv_sec;
2078 newpeer->id = strdup(args[1]);
2079
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002080 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002081 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01002082 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002083 err_code |= ERR_ALERT | ERR_FATAL;
2084 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002085 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01002086
2087 proto = protocol_by_family(sk->ss_family);
2088 if (!proto || !proto->connect) {
2089 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2090 file, linenum, args[0], args[1]);
2091 err_code |= ERR_ALERT | ERR_FATAL;
2092 goto out;
2093 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002094
2095 if (port1 != port2) {
2096 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2097 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002098 err_code |= ERR_ALERT | ERR_FATAL;
2099 goto out;
2100 }
2101
Willy Tarreau2aa38802013-02-20 19:20:59 +01002102 if (!port1) {
2103 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2104 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002105 err_code |= ERR_ALERT | ERR_FATAL;
2106 goto out;
2107 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002108
Emeric Brun32da3c42010-09-23 18:39:19 +02002109 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002110 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002111 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02002112 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02002113
Emeric Brun32da3c42010-09-23 18:39:19 +02002114 if (strcmp(newpeer->id, localpeer) == 0) {
2115 /* Current is local peer, it define a frontend */
2116 newpeer->local = 1;
Emeric Brunb3971ab2015-05-12 18:49:09 +02002117 peers->local = newpeer;
Emeric Brun32da3c42010-09-23 18:39:19 +02002118
2119 if (!curpeers->peers_fe) {
2120 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
2121 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2122 err_code |= ERR_ALERT | ERR_ABORT;
2123 goto out;
2124 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002125
Willy Tarreau237250c2011-07-29 01:49:03 +02002126 init_new_proxy(curpeers->peers_fe);
2127 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02002128 curpeers->peers_fe->id = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002129 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
2130 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau91d96282015-03-13 15:47:26 +01002131 peers_setup_frontend(curpeers->peers_fe);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002132
2133 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
2134
Willy Tarreau902636f2013-03-10 19:44:48 +01002135 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
2136 if (errmsg && *errmsg) {
2137 indent_msg(&errmsg, 2);
2138 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002139 }
2140 else
2141 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
2142 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002143 err_code |= ERR_FATAL;
2144 goto out;
2145 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02002146
2147 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01002148 l->maxaccept = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002149 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
2150 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
Willy Tarreau9903f0e2015-04-04 18:50:31 +02002151 l->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02002152 l->handler = process_stream;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002153 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01002154 l->default_target = ((struct proxy *)curpeers->peers_fe)->default_target;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002155 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
2156 global.maxsock += l->maxconn;
2157 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002158 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01002159 else {
2160 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
2161 file, linenum, args[0], args[1],
2162 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
2163 err_code |= ERR_FATAL;
2164 goto out;
2165 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002166 }
2167 } /* neither "peer" nor "peers" */
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002168 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
2169 curpeers->state = PR_STSTOPPED;
2170 }
2171 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
2172 curpeers->state = PR_STNEW;
2173 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002174 else if (*args[0] != 0) {
2175 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2176 err_code |= ERR_ALERT | ERR_FATAL;
2177 goto out;
2178 }
2179
2180out:
Willy Tarreau902636f2013-03-10 19:44:48 +01002181 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02002182 return err_code;
2183}
2184
Baptiste Assmann325137d2015-04-13 23:40:55 +02002185/*
2186 * Parse a <resolvers> section.
2187 * Returns the error code, 0 if OK, or any combination of :
2188 * - ERR_ABORT: must abort ASAP
2189 * - ERR_FATAL: we can continue parsing but not start the service
2190 * - ERR_WARN: a warning has been emitted
2191 * - ERR_ALERT: an alert has been emitted
2192 * Only the two first ones can stop processing, the two others are just
2193 * indicators.
2194 */
2195int cfg_parse_resolvers(const char *file, int linenum, char **args, int kwm)
2196{
2197 static struct dns_resolvers *curr_resolvers = NULL;
2198 struct dns_nameserver *newnameserver = NULL;
2199 const char *err;
2200 int err_code = 0;
2201 char *errmsg = NULL;
2202
2203 if (strcmp(args[0], "resolvers") == 0) { /* new resolvers section */
2204 if (!*args[1]) {
2205 Alert("parsing [%s:%d] : missing name for resolvers section.\n", file, linenum);
2206 err_code |= ERR_ALERT | ERR_ABORT;
2207 goto out;
2208 }
2209
2210 err = invalid_char(args[1]);
2211 if (err) {
2212 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2213 file, linenum, *err, args[0], args[1]);
2214 err_code |= ERR_ALERT | ERR_ABORT;
2215 goto out;
2216 }
2217
2218 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
2219 /* Error if two resolvers owns the same name */
2220 if (strcmp(curr_resolvers->id, args[1]) == 0) {
2221 Alert("Parsing [%s:%d]: resolvers '%s' has same name as another resolvers (declared at %s:%d).\n",
2222 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2223 err_code |= ERR_ALERT | ERR_ABORT;
2224 }
2225 }
2226
2227 if ((curr_resolvers = (struct dns_resolvers *)calloc(1, sizeof(struct dns_resolvers))) == NULL) {
2228 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2229 err_code |= ERR_ALERT | ERR_ABORT;
2230 goto out;
2231 }
2232
2233 /* default values */
2234 LIST_ADDQ(&dns_resolvers, &curr_resolvers->list);
2235 curr_resolvers->conf.file = strdup(file);
2236 curr_resolvers->conf.line = linenum;
2237 curr_resolvers->id = strdup(args[1]);
2238 curr_resolvers->query_ids = EB_ROOT;
2239 /* default hold period for valid is 10s */
Baptiste Assmann4c5490a2015-07-14 21:42:49 +02002240 curr_resolvers->hold.valid = 10000;
2241 curr_resolvers->timeout.retry = 1000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002242 curr_resolvers->resolve_retries = 3;
2243 LIST_INIT(&curr_resolvers->nameserver_list);
2244 LIST_INIT(&curr_resolvers->curr_resolution);
2245 }
2246 else if (strcmp(args[0], "nameserver") == 0) { /* nameserver definition */
2247 struct sockaddr_storage *sk;
2248 int port1, port2;
2249 struct protocol *proto;
2250
2251 if (!*args[2]) {
2252 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2253 file, linenum, args[0]);
2254 err_code |= ERR_ALERT | ERR_FATAL;
2255 goto out;
2256 }
2257
2258 err = invalid_char(args[1]);
2259 if (err) {
2260 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2261 file, linenum, *err, args[1]);
2262 err_code |= ERR_ALERT | ERR_FATAL;
2263 goto out;
2264 }
2265
2266 if ((newnameserver = (struct dns_nameserver *)calloc(1, sizeof(struct dns_nameserver))) == NULL) {
2267 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2268 err_code |= ERR_ALERT | ERR_ABORT;
2269 goto out;
2270 }
2271
2272 /* the nameservers are linked backward first */
2273 LIST_ADDQ(&curr_resolvers->nameserver_list, &newnameserver->list);
2274 curr_resolvers->count_nameservers++;
2275 newnameserver->resolvers = curr_resolvers;
2276 newnameserver->conf.file = strdup(file);
2277 newnameserver->conf.line = linenum;
2278 newnameserver->id = strdup(args[1]);
2279
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002280 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002281 if (!sk) {
2282 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2283 err_code |= ERR_ALERT | ERR_FATAL;
2284 goto out;
2285 }
2286
2287 proto = protocol_by_family(sk->ss_family);
2288 if (!proto || !proto->connect) {
2289 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2290 file, linenum, args[0], args[1]);
2291 err_code |= ERR_ALERT | ERR_FATAL;
2292 goto out;
2293 }
2294
2295 if (port1 != port2) {
2296 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2297 file, linenum, args[0], args[1], args[2]);
2298 err_code |= ERR_ALERT | ERR_FATAL;
2299 goto out;
2300 }
2301
2302 newnameserver->addr = *sk;
2303 }
2304 else if (strcmp(args[0], "hold") == 0) { /* hold periods */
2305 const char *res;
2306 unsigned int time;
2307
2308 if (!*args[2]) {
2309 Alert("parsing [%s:%d] : '%s' expects an <event> and a <time> as arguments.\n",
2310 file, linenum, args[0]);
2311 Alert("<event> can be either 'valid', 'nx', 'refused', 'timeout', or 'other'\n");
2312 err_code |= ERR_ALERT | ERR_FATAL;
2313 goto out;
2314 }
2315 res = parse_time_err(args[2], &time, TIME_UNIT_MS);
2316 if (res) {
2317 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2318 file, linenum, *res, args[0]);
2319 err_code |= ERR_ALERT | ERR_FATAL;
2320 goto out;
2321 }
2322 if (strcmp(args[1], "valid") == 0)
2323 curr_resolvers->hold.valid = time;
2324 else {
2325 Alert("parsing [%s:%d] : '%s' unknown <event>: '%s', expects 'valid'\n",
2326 file, linenum, args[0], args[1]);
2327 err_code |= ERR_ALERT | ERR_FATAL;
2328 goto out;
2329 }
2330
2331 }
2332 else if (strcmp(args[0], "resolve_retries") == 0) {
2333 if (!*args[1]) {
2334 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2335 file, linenum, args[0]);
2336 err_code |= ERR_ALERT | ERR_FATAL;
2337 goto out;
2338 }
2339 curr_resolvers->resolve_retries = atoi(args[1]);
2340 }
2341 else if (strcmp(args[0], "timeout") == 0) {
2342 const char *res;
2343 unsigned int timeout_retry;
2344
2345 if (!*args[2]) {
2346 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments.\n",
2347 file, linenum, args[0]);
2348 err_code |= ERR_ALERT | ERR_FATAL;
2349 goto out;
2350 }
2351 res = parse_time_err(args[2], &timeout_retry, TIME_UNIT_MS);
2352 if (res) {
2353 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2354 file, linenum, *res, args[0]);
2355 err_code |= ERR_ALERT | ERR_FATAL;
2356 goto out;
2357 }
2358 curr_resolvers->timeout.retry = timeout_retry;
2359 } /* neither "nameserver" nor "resolvers" */
2360 else if (*args[0] != 0) {
2361 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2362 err_code |= ERR_ALERT | ERR_FATAL;
2363 goto out;
2364 }
2365
2366 out:
2367 free(errmsg);
2368 return err_code;
2369}
Simon Horman0d16a402015-01-30 11:22:58 +09002370
2371/*
William Lallemand51097192015-04-14 16:35:22 +02002372 * Parse a line in a <listen>, <frontend> or <backend> section.
Simon Horman0d16a402015-01-30 11:22:58 +09002373 * Returns the error code, 0 if OK, or any combination of :
2374 * - ERR_ABORT: must abort ASAP
2375 * - ERR_FATAL: we can continue parsing but not start the service
2376 * - ERR_WARN: a warning has been emitted
2377 * - ERR_ALERT: an alert has been emitted
2378 * Only the two first ones can stop processing, the two others are just
2379 * indicators.
2380 */
2381int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
2382{
2383 static struct mailers *curmailers = NULL;
2384 struct mailer *newmailer = NULL;
2385 const char *err;
2386 int err_code = 0;
2387 char *errmsg = NULL;
2388
2389 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
2390 if (!*args[1]) {
2391 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
2392 err_code |= ERR_ALERT | ERR_ABORT;
2393 goto out;
2394 }
2395
2396 err = invalid_char(args[1]);
2397 if (err) {
2398 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2399 file, linenum, *err, args[0], args[1]);
2400 err_code |= ERR_ALERT | ERR_ABORT;
2401 goto out;
2402 }
2403
2404 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
2405 /*
2406 * If there are two proxies with the same name only following
2407 * combinations are allowed:
2408 */
2409 if (strcmp(curmailers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002410 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 +09002411 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002412 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman0d16a402015-01-30 11:22:58 +09002413 }
2414 }
2415
2416 if ((curmailers = (struct mailers *)calloc(1, sizeof(struct mailers))) == NULL) {
2417 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2418 err_code |= ERR_ALERT | ERR_ABORT;
2419 goto out;
2420 }
2421
2422 curmailers->next = mailers;
2423 mailers = curmailers;
2424 curmailers->conf.file = strdup(file);
2425 curmailers->conf.line = linenum;
2426 curmailers->id = strdup(args[1]);
2427 }
2428 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
2429 struct sockaddr_storage *sk;
2430 int port1, port2;
2431 struct protocol *proto;
2432
2433 if (!*args[2]) {
2434 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2435 file, linenum, args[0]);
2436 err_code |= ERR_ALERT | ERR_FATAL;
2437 goto out;
2438 }
2439
2440 err = invalid_char(args[1]);
2441 if (err) {
2442 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2443 file, linenum, *err, args[1]);
2444 err_code |= ERR_ALERT | ERR_FATAL;
2445 goto out;
2446 }
2447
2448 if ((newmailer = (struct mailer *)calloc(1, sizeof(struct mailer))) == NULL) {
2449 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2450 err_code |= ERR_ALERT | ERR_ABORT;
2451 goto out;
2452 }
2453
2454 /* the mailers are linked backwards first */
2455 curmailers->count++;
2456 newmailer->next = curmailers->mailer_list;
2457 curmailers->mailer_list = newmailer;
2458 newmailer->mailers = curmailers;
2459 newmailer->conf.file = strdup(file);
2460 newmailer->conf.line = linenum;
2461
2462 newmailer->id = strdup(args[1]);
2463
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002464 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Simon Horman0d16a402015-01-30 11:22:58 +09002465 if (!sk) {
2466 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2467 err_code |= ERR_ALERT | ERR_FATAL;
2468 goto out;
2469 }
2470
2471 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002472 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2473 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002474 file, linenum, args[0], args[1]);
2475 err_code |= ERR_ALERT | ERR_FATAL;
2476 goto out;
2477 }
2478
2479 if (port1 != port2) {
2480 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2481 file, linenum, args[0], args[1], args[2]);
2482 err_code |= ERR_ALERT | ERR_FATAL;
2483 goto out;
2484 }
2485
2486 if (!port1) {
2487 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2488 file, linenum, args[0], args[1], args[2]);
2489 err_code |= ERR_ALERT | ERR_FATAL;
2490 goto out;
2491 }
2492
2493 newmailer->addr = *sk;
2494 newmailer->proto = proto;
2495 newmailer->xprt = &raw_sock;
2496 newmailer->sock_init_arg = NULL;
2497 } /* neither "mailer" nor "mailers" */
2498 else if (*args[0] != 0) {
2499 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2500 err_code |= ERR_ALERT | ERR_FATAL;
2501 goto out;
2502 }
2503
2504out:
2505 free(errmsg);
2506 return err_code;
2507}
2508
Simon Horman9dc49962015-01-30 11:22:59 +09002509static void free_email_alert(struct proxy *p)
2510{
2511 free(p->email_alert.mailers.name);
2512 p->email_alert.mailers.name = NULL;
2513 free(p->email_alert.from);
2514 p->email_alert.from = NULL;
2515 free(p->email_alert.to);
2516 p->email_alert.to = NULL;
2517 free(p->email_alert.myhostname);
2518 p->email_alert.myhostname = NULL;
2519}
2520
Willy Tarreau3842f002009-06-14 11:39:52 +02002521int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002522{
2523 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002524 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002525 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002526 int rc;
2527 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002528 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002529 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002530 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002531 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002532 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002533
Willy Tarreau977b8e42006-12-29 14:19:17 +01002534 if (!strcmp(args[0], "listen"))
2535 rc = PR_CAP_LISTEN;
2536 else if (!strcmp(args[0], "frontend"))
2537 rc = PR_CAP_FE | PR_CAP_RS;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02002538 else if (!strcmp(args[0], "backend"))
Willy Tarreau977b8e42006-12-29 14:19:17 +01002539 rc = PR_CAP_BE | PR_CAP_RS;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002540 else
2541 rc = PR_CAP_NONE;
2542
2543 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002544 if (!*args[1]) {
2545 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
2546 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
2547 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002548 err_code |= ERR_ALERT | ERR_ABORT;
2549 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002550 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002551
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002552 err = invalid_char(args[1]);
2553 if (err) {
2554 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2555 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002556 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002557 }
2558
Willy Tarreau8f50b682015-05-26 11:45:02 +02002559 curproxy = (rc & PR_CAP_FE) ? proxy_fe_by_name(args[1]) : proxy_be_by_name(args[1]);
2560 if (curproxy) {
2561 Alert("Parsing [%s:%d]: %s '%s' has the same name as %s '%s' declared at %s:%d.\n",
2562 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2563 curproxy->id, curproxy->conf.file, curproxy->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002564 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002565 }
2566
Willy Tarreaubaaee002006-06-26 02:48:02 +02002567 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
2568 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002569 err_code |= ERR_ALERT | ERR_ABORT;
2570 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002571 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002572
Willy Tarreau97cb7802010-01-03 20:23:58 +01002573 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002574 curproxy->next = proxy;
2575 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002576 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2577 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002578 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002579 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002580 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002581 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002582
William Lallemand6e62fb62015-04-28 16:55:23 +02002583 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2584 if (curproxy->cap & PR_CAP_FE)
2585 Alert("parsing [%s:%d] : please use the 'bind' keyword for listening addresses.\n", file, linenum);
2586 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002587 }
2588
2589 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002590 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002591 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002592
Willy Tarreaubaaee002006-06-26 02:48:02 +02002593 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002594 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002595 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002596 curproxy->no_options = defproxy.no_options;
2597 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002598 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002599 curproxy->except_net = defproxy.except_net;
2600 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002601 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002602 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002603
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002604 if (defproxy.fwdfor_hdr_len) {
2605 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2606 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2607 }
2608
Willy Tarreaub86db342009-11-30 11:50:16 +01002609 if (defproxy.orgto_hdr_len) {
2610 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2611 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2612 }
2613
Mark Lamourinec2247f02012-01-04 13:02:01 -05002614 if (defproxy.server_id_hdr_len) {
2615 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2616 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2617 }
2618
Willy Tarreau977b8e42006-12-29 14:19:17 +01002619 if (curproxy->cap & PR_CAP_FE) {
2620 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002621 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002622 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002623
2624 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002625 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2626 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002627
2628 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2629 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002630
Willy Tarreau977b8e42006-12-29 14:19:17 +01002631 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002632 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002633 curproxy->fullconn = defproxy.fullconn;
2634 curproxy->conn_retries = defproxy.conn_retries;
Joseph Lynch726ab712015-05-11 23:25:34 -07002635 curproxy->redispatch_after = defproxy.redispatch_after;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002636 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002637
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002638 if (defproxy.check_req) {
2639 curproxy->check_req = calloc(1, defproxy.check_len);
2640 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2641 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002642 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002643
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002644 if (defproxy.expect_str) {
2645 curproxy->expect_str = strdup(defproxy.expect_str);
2646 if (defproxy.expect_regex) {
2647 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002648 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2649 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002650 }
2651 }
2652
Willy Tarreau67402132012-05-31 20:40:20 +02002653 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002654 if (defproxy.cookie_name)
2655 curproxy->cookie_name = strdup(defproxy.cookie_name);
2656 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002657 if (defproxy.cookie_domain)
2658 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002659
Willy Tarreau31936852010-10-06 16:59:56 +02002660 if (defproxy.cookie_maxidle)
2661 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2662
2663 if (defproxy.cookie_maxlife)
2664 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2665
Emeric Brun647caf12009-06-30 17:57:00 +02002666 if (defproxy.rdp_cookie_name)
2667 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2668 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2669
Willy Tarreau01732802007-11-01 22:48:15 +01002670 if (defproxy.url_param_name)
2671 curproxy->url_param_name = strdup(defproxy.url_param_name);
2672 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002673
Benoitaffb4812009-03-25 13:02:10 +01002674 if (defproxy.hh_name)
2675 curproxy->hh_name = strdup(defproxy.hh_name);
2676 curproxy->hh_len = defproxy.hh_len;
2677 curproxy->hh_match_domain = defproxy.hh_match_domain;
2678
Willy Tarreauef9a3602012-12-08 22:29:20 +01002679 if (defproxy.conn_src.iface_name)
2680 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2681 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002682 curproxy->conn_src.opts = defproxy.conn_src.opts;
Willy Tarreau29fbe512015-08-20 19:35:14 +02002683#if defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002684 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002685#endif
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02002686 curproxy->load_server_state_from_file = defproxy.load_server_state_from_file;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002687 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002688
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002689 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002690 if (defproxy.capture_name)
2691 curproxy->capture_name = strdup(defproxy.capture_name);
2692 curproxy->capture_namelen = defproxy.capture_namelen;
2693 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002694 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002695
Willy Tarreau977b8e42006-12-29 14:19:17 +01002696 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002697 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002698 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002699 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002700 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002701 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002702 curproxy->mon_net = defproxy.mon_net;
2703 curproxy->mon_mask = defproxy.mon_mask;
2704 if (defproxy.monitor_uri)
2705 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2706 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002707 if (defproxy.defbe.name)
2708 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002709
2710 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002711 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2712 if (curproxy->conf.logformat_string &&
2713 curproxy->conf.logformat_string != default_http_log_format &&
2714 curproxy->conf.logformat_string != default_tcp_log_format &&
2715 curproxy->conf.logformat_string != clf_http_log_format)
2716 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2717
2718 if (defproxy.conf.lfs_file) {
2719 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2720 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2721 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002722
2723 /* get either a pointer to the logformat string for RFC5424 structured-data or a copy of it */
2724 curproxy->conf.logformat_sd_string = defproxy.conf.logformat_sd_string;
2725 if (curproxy->conf.logformat_sd_string &&
2726 curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
2727 curproxy->conf.logformat_sd_string = strdup(curproxy->conf.logformat_sd_string);
2728
2729 if (defproxy.conf.lfsd_file) {
2730 curproxy->conf.lfsd_file = strdup(defproxy.conf.lfsd_file);
2731 curproxy->conf.lfsd_line = defproxy.conf.lfsd_line;
2732 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002733 }
2734
2735 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002736 curproxy->timeout.connect = defproxy.timeout.connect;
2737 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002738 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002739 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002740 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002741 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002742 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002743 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002744 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002745 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002746 }
2747
Willy Tarreaubaaee002006-06-26 02:48:02 +02002748 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002749 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002750
2751 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002752 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002753 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002754 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002755 LIST_INIT(&node->list);
2756 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2757 }
2758
Willy Tarreau62a61232013-04-12 18:13:46 +02002759 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2760 if (curproxy->conf.uniqueid_format_string)
2761 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2762
Willy Tarreau094af4e2015-01-07 15:03:42 +01002763 if (defproxy.log_tag)
2764 curproxy->log_tag = strdup(defproxy.log_tag);
2765
Willy Tarreau62a61232013-04-12 18:13:46 +02002766 if (defproxy.conf.uif_file) {
2767 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2768 curproxy->conf.uif_line = defproxy.conf.uif_line;
2769 }
William Lallemanda73203e2012-03-12 12:48:57 +01002770
2771 /* copy default header unique id */
2772 if (defproxy.header_unique_id)
2773 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2774
William Lallemand82fe75c2012-10-23 10:25:10 +02002775 /* default compression options */
2776 if (defproxy.comp != NULL) {
2777 curproxy->comp = calloc(1, sizeof(struct comp));
2778 curproxy->comp->algos = defproxy.comp->algos;
2779 curproxy->comp->types = defproxy.comp->types;
2780 }
2781
Willy Tarreaubaaee002006-06-26 02:48:02 +02002782 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002783 curproxy->conf.used_listener_id = EB_ROOT;
2784 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002785
Simon Horman98637e52014-06-20 12:30:16 +09002786 if (defproxy.check_path)
2787 curproxy->check_path = strdup(defproxy.check_path);
2788 if (defproxy.check_command)
2789 curproxy->check_command = strdup(defproxy.check_command);
2790
Simon Horman9dc49962015-01-30 11:22:59 +09002791 if (defproxy.email_alert.mailers.name)
2792 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2793 if (defproxy.email_alert.from)
2794 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2795 if (defproxy.email_alert.to)
2796 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2797 if (defproxy.email_alert.myhostname)
2798 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09002799 curproxy->email_alert.level = defproxy.email_alert.level;
Simon Horman9dc49962015-01-30 11:22:59 +09002800
Willy Tarreau93893792009-07-23 13:19:11 +02002801 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002802 }
2803 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2804 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002805 /* FIXME-20070101: we should do this too at the end of the
2806 * config parsing to free all default values.
2807 */
William Lallemand6e62fb62015-04-28 16:55:23 +02002808 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2809 err_code |= ERR_ABORT;
2810 goto out;
2811 }
2812
Willy Tarreaua534fea2008-08-03 12:19:50 +02002813 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002814 free(defproxy.check_command);
2815 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002816 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002817 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002818 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002819 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002820 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002821 free(defproxy.capture_name);
2822 free(defproxy.monitor_uri);
2823 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002824 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002825 free(defproxy.fwdfor_hdr_name);
2826 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002827 free(defproxy.orgto_hdr_name);
2828 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002829 free(defproxy.server_id_hdr_name);
2830 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002831 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002832 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002833 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002834 free(defproxy.expect_regex);
2835 defproxy.expect_regex = NULL;
2836 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002837
Willy Tarreau62a61232013-04-12 18:13:46 +02002838 if (defproxy.conf.logformat_string != default_http_log_format &&
2839 defproxy.conf.logformat_string != default_tcp_log_format &&
2840 defproxy.conf.logformat_string != clf_http_log_format)
2841 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002842
Willy Tarreau62a61232013-04-12 18:13:46 +02002843 free(defproxy.conf.uniqueid_format_string);
2844 free(defproxy.conf.lfs_file);
2845 free(defproxy.conf.uif_file);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002846 free(defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09002847 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02002848
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002849 if (defproxy.conf.logformat_sd_string != default_rfc5424_sd_log_format)
2850 free(defproxy.conf.logformat_sd_string);
2851 free(defproxy.conf.lfsd_file);
2852
Willy Tarreaua534fea2008-08-03 12:19:50 +02002853 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002854 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002855
Willy Tarreaubaaee002006-06-26 02:48:02 +02002856 /* we cannot free uri_auth because it might already be used */
2857 init_default_instance();
2858 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002859 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2860 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002861 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002862 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002863 }
2864 else if (curproxy == NULL) {
2865 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002866 err_code |= ERR_ALERT | ERR_FATAL;
2867 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002868 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002869
2870 /* update the current file and line being parsed */
2871 curproxy->conf.args.file = curproxy->conf.file;
2872 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002873
2874 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002875 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2876 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2877 if (err_code & ERR_FATAL)
2878 goto out;
2879 }
2880 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002881 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002882 int cur_arg;
2883
Willy Tarreaubaaee002006-06-26 02:48:02 +02002884 if (curproxy == &defproxy) {
2885 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002886 err_code |= ERR_ALERT | ERR_FATAL;
2887 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002888 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002889 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002890 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002891
Willy Tarreau24709282013-03-10 21:32:12 +01002892 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002893 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002894 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002895 err_code |= ERR_ALERT | ERR_FATAL;
2896 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002897 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002898
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002899 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002900
2901 /* use default settings for unix sockets */
2902 bind_conf->ux.uid = global.unix_bind.ux.uid;
2903 bind_conf->ux.gid = global.unix_bind.ux.gid;
2904 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002905
2906 /* NOTE: the following line might create several listeners if there
2907 * are comma-separated IPs or port ranges. So all further processing
2908 * will have to be applied to all listeners created after last_listen.
2909 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002910 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2911 if (errmsg && *errmsg) {
2912 indent_msg(&errmsg, 2);
2913 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002914 }
2915 else
2916 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2917 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002918 err_code |= ERR_ALERT | ERR_FATAL;
2919 goto out;
2920 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002921
Willy Tarreau4348fad2012-09-20 16:48:07 +02002922 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2923 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002924 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002925 }
2926
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002927 cur_arg = 2;
2928 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002929 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002930 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002931 char *err;
2932
Willy Tarreau26982662012-09-12 23:17:10 +02002933 kw = bind_find_kw(args[cur_arg]);
2934 if (kw) {
2935 char *err = NULL;
2936 int code;
2937
2938 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002939 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2940 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002941 cur_arg += 1 + kw->skip ;
2942 err_code |= ERR_ALERT | ERR_FATAL;
2943 goto out;
2944 }
2945
Willy Tarreau4348fad2012-09-20 16:48:07 +02002946 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002947 err_code |= code;
2948
2949 if (code) {
2950 if (err && *err) {
2951 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002952 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002953 }
2954 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002955 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2956 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002957 if (code & ERR_FATAL) {
2958 free(err);
2959 cur_arg += 1 + kw->skip;
2960 goto out;
2961 }
2962 }
2963 free(err);
2964 cur_arg += 1 + kw->skip;
2965 continue;
2966 }
2967
Willy Tarreau8638f482012-09-18 18:01:17 +02002968 err = NULL;
2969 if (!bind_dumped) {
2970 bind_dump_kws(&err);
2971 indent_msg(&err, 4);
2972 bind_dumped = 1;
2973 }
2974
2975 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2976 file, linenum, args[0], args[1], args[cur_arg],
2977 err ? " Registered keywords :" : "", err ? err : "");
2978 free(err);
2979
Willy Tarreau93893792009-07-23 13:19:11 +02002980 err_code |= ERR_ALERT | ERR_FATAL;
2981 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002982 }
Willy Tarreau93893792009-07-23 13:19:11 +02002983 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002984 }
2985 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002986 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002987 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2988 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002989 err_code |= ERR_ALERT | ERR_FATAL;
2990 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002991 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002992 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002993 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002994
Willy Tarreaubaaee002006-06-26 02:48:02 +02002995 /* flush useless bits */
2996 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002997 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002998 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002999 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003000 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003001 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003002
William Lallemanddf1425a2015-04-28 20:17:49 +02003003 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3004 goto out;
3005
Willy Tarreau1c47f852006-07-09 08:22:27 +02003006 if (!*args[1]) {
3007 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
3008 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003009 err_code |= ERR_ALERT | ERR_FATAL;
3010 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003011 }
3012
Willy Tarreaua534fea2008-08-03 12:19:50 +02003013 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003014 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02003015 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003016 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02003017 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
3018
Willy Tarreau93893792009-07-23 13:19:11 +02003019 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003020 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003021 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
William Lallemanddf1425a2015-04-28 20:17:49 +02003022 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3023 goto out;
3024
Willy Tarreaubaaee002006-06-26 02:48:02 +02003025 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
3026 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
3027 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
3028 else {
3029 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003030 err_code |= ERR_ALERT | ERR_FATAL;
3031 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003032 }
3033 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003034 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003035 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003036
3037 if (curproxy == &defproxy) {
3038 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3039 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003040 err_code |= ERR_ALERT | ERR_FATAL;
3041 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003042 }
3043
William Lallemanddf1425a2015-04-28 20:17:49 +02003044 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3045 goto out;
3046
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003047 if (!*args[1]) {
3048 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3049 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003050 err_code |= ERR_ALERT | ERR_FATAL;
3051 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003052 }
3053
3054 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003055 curproxy->conf.id.key = curproxy->uuid;
Willy Tarreau0d1fdf72015-05-27 16:44:02 +02003056 curproxy->options |= PR_O_FORCED_ID;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003057
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003058 if (curproxy->uuid <= 0) {
3059 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003060 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003061 err_code |= ERR_ALERT | ERR_FATAL;
3062 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003063 }
3064
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003065 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
3066 if (node) {
3067 struct proxy *target = container_of(node, struct proxy, conf.id);
3068 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
3069 file, linenum, proxy_type_str(curproxy), curproxy->id,
3070 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
3071 err_code |= ERR_ALERT | ERR_FATAL;
3072 goto out;
3073 }
3074 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003075 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003076 else if (!strcmp(args[0], "description")) {
3077 int i, len=0;
3078 char *d;
3079
Cyril Bonté99ed3272010-01-24 23:29:44 +01003080 if (curproxy == &defproxy) {
3081 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3082 file, linenum, args[0]);
3083 err_code |= ERR_ALERT | ERR_FATAL;
3084 goto out;
3085 }
3086
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003087 if (!*args[1]) {
3088 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
3089 file, linenum, args[0]);
3090 return -1;
3091 }
3092
Willy Tarreau348acfe2014-04-14 15:00:39 +02003093 for (i = 1; *args[i]; i++)
3094 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003095
3096 d = (char *)calloc(1, len);
3097 curproxy->desc = d;
3098
Willy Tarreau348acfe2014-04-14 15:00:39 +02003099 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
3100 for (i = 2; *args[i]; i++)
3101 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003102
3103 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003104 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
William Lallemanddf1425a2015-04-28 20:17:49 +02003105 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3106 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003107 curproxy->state = PR_STSTOPPED;
3108 }
3109 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
William Lallemanddf1425a2015-04-28 20:17:49 +02003110 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3111 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003112 curproxy->state = PR_STNEW;
3113 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003114 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
3115 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003116 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003117
3118 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003119 unsigned int low, high;
3120
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003121 if (strcmp(args[cur_arg], "all") == 0) {
3122 set = 0;
3123 break;
3124 }
3125 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003126 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003127 }
3128 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003129 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003130 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01003131 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003132 char *dash = strchr(args[cur_arg], '-');
3133
3134 low = high = str2uic(args[cur_arg]);
3135 if (dash)
3136 high = str2uic(dash + 1);
3137
3138 if (high < low) {
3139 unsigned int swap = low;
3140 low = high;
3141 high = swap;
3142 }
3143
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003144 if (low < 1 || high > LONGBITS) {
3145 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
3146 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02003147 err_code |= ERR_ALERT | ERR_FATAL;
3148 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003149 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01003150 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003151 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003152 }
3153 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003154 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
3155 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003156 err_code |= ERR_ALERT | ERR_FATAL;
3157 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003158 }
3159 cur_arg++;
3160 }
3161 curproxy->bind_proc = set;
3162 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003163 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02003164 if (curproxy == &defproxy) {
3165 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003166 err_code |= ERR_ALERT | ERR_FATAL;
3167 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003168 }
3169
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003170 err = invalid_char(args[1]);
3171 if (err) {
3172 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
3173 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003174 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003175 }
3176
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01003177 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003178 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
3179 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003180 err_code |= ERR_ALERT | ERR_FATAL;
3181 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003182 }
3183 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003184 else if (!strcmp(args[0], "cookie")) { /* cookie name */
3185 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003186
Willy Tarreau977b8e42006-12-29 14:19:17 +01003187 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003188 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003189
Willy Tarreaubaaee002006-06-26 02:48:02 +02003190 if (*(args[1]) == 0) {
3191 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
3192 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003193 err_code |= ERR_ALERT | ERR_FATAL;
3194 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003195 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003196
Willy Tarreau67402132012-05-31 20:40:20 +02003197 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003198 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01003199 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003200 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003201 curproxy->cookie_name = strdup(args[1]);
3202 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003203
Willy Tarreaubaaee002006-06-26 02:48:02 +02003204 cur_arg = 2;
3205 while (*(args[cur_arg])) {
3206 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003207 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003208 }
3209 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003210 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003211 }
3212 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003213 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003214 }
3215 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003216 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003217 }
3218 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003219 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003220 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003221 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003222 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003223 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003224 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003225 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003226 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02003227 else if (!strcmp(args[cur_arg], "httponly")) {
3228 curproxy->ck_opts |= PR_CK_HTTPONLY;
3229 }
3230 else if (!strcmp(args[cur_arg], "secure")) {
3231 curproxy->ck_opts |= PR_CK_SECURE;
3232 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003233 else if (!strcmp(args[cur_arg], "domain")) {
3234 if (!*args[cur_arg + 1]) {
3235 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
3236 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003237 err_code |= ERR_ALERT | ERR_FATAL;
3238 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003239 }
3240
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003241 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003242 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003243 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
3244 " dots nor does not start with a dot."
3245 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003246 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003247 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003248 }
3249
3250 err = invalid_domainchar(args[cur_arg + 1]);
3251 if (err) {
3252 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
3253 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003254 err_code |= ERR_ALERT | ERR_FATAL;
3255 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003256 }
3257
Willy Tarreau68a897b2009-12-03 23:28:34 +01003258 if (!curproxy->cookie_domain) {
3259 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
3260 } else {
3261 /* one domain was already specified, add another one by
3262 * building the string which will be returned along with
3263 * the cookie.
3264 */
3265 char *new_ptr;
3266 int new_len = strlen(curproxy->cookie_domain) +
3267 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
3268 new_ptr = malloc(new_len);
3269 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
3270 free(curproxy->cookie_domain);
3271 curproxy->cookie_domain = new_ptr;
3272 }
Willy Tarreau31936852010-10-06 16:59:56 +02003273 cur_arg++;
3274 }
3275 else if (!strcmp(args[cur_arg], "maxidle")) {
3276 unsigned int maxidle;
3277 const char *res;
3278
3279 if (!*args[cur_arg + 1]) {
3280 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
3281 file, linenum, args[cur_arg]);
3282 err_code |= ERR_ALERT | ERR_FATAL;
3283 goto out;
3284 }
3285
3286 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
3287 if (res) {
3288 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3289 file, linenum, *res, args[cur_arg]);
3290 err_code |= ERR_ALERT | ERR_FATAL;
3291 goto out;
3292 }
3293 curproxy->cookie_maxidle = maxidle;
3294 cur_arg++;
3295 }
3296 else if (!strcmp(args[cur_arg], "maxlife")) {
3297 unsigned int maxlife;
3298 const char *res;
3299
3300 if (!*args[cur_arg + 1]) {
3301 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
3302 file, linenum, args[cur_arg]);
3303 err_code |= ERR_ALERT | ERR_FATAL;
3304 goto out;
3305 }
3306
3307 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
3308 if (res) {
3309 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3310 file, linenum, *res, args[cur_arg]);
3311 err_code |= ERR_ALERT | ERR_FATAL;
3312 goto out;
3313 }
3314 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003315 cur_arg++;
3316 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003317 else {
Willy Tarreau31936852010-10-06 16:59:56 +02003318 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 +02003319 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003320 err_code |= ERR_ALERT | ERR_FATAL;
3321 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003322 }
3323 cur_arg++;
3324 }
Willy Tarreau67402132012-05-31 20:40:20 +02003325 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003326 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
3327 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003328 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003329 }
3330
Willy Tarreau67402132012-05-31 20:40:20 +02003331 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003332 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
3333 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003334 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003335 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003336
Willy Tarreau67402132012-05-31 20:40:20 +02003337 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003338 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
3339 file, linenum);
3340 err_code |= ERR_ALERT | ERR_FATAL;
3341 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003342 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09003343 else if (!strcmp(args[0], "email-alert")) {
3344 if (*(args[1]) == 0) {
3345 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3346 file, linenum, args[0]);
3347 err_code |= ERR_ALERT | ERR_FATAL;
3348 goto out;
3349 }
3350
3351 if (!strcmp(args[1], "from")) {
3352 if (*(args[1]) == 0) {
3353 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3354 file, linenum, args[1]);
3355 err_code |= ERR_ALERT | ERR_FATAL;
3356 goto out;
3357 }
3358 free(curproxy->email_alert.from);
3359 curproxy->email_alert.from = strdup(args[2]);
3360 }
3361 else if (!strcmp(args[1], "mailers")) {
3362 if (*(args[1]) == 0) {
3363 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3364 file, linenum, args[1]);
3365 err_code |= ERR_ALERT | ERR_FATAL;
3366 goto out;
3367 }
3368 free(curproxy->email_alert.mailers.name);
3369 curproxy->email_alert.mailers.name = strdup(args[2]);
3370 }
3371 else if (!strcmp(args[1], "myhostname")) {
3372 if (*(args[1]) == 0) {
3373 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3374 file, linenum, args[1]);
3375 err_code |= ERR_ALERT | ERR_FATAL;
3376 goto out;
3377 }
3378 free(curproxy->email_alert.myhostname);
3379 curproxy->email_alert.myhostname = strdup(args[2]);
3380 }
Simon Horman64e34162015-02-06 11:11:57 +09003381 else if (!strcmp(args[1], "level")) {
3382 curproxy->email_alert.level = get_log_level(args[2]);
3383 if (curproxy->email_alert.level < 0) {
3384 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
3385 file, linenum, args[1], args[2]);
3386 err_code |= ERR_ALERT | ERR_FATAL;
3387 goto out;
3388 }
3389 }
Simon Horman9dc49962015-01-30 11:22:59 +09003390 else if (!strcmp(args[1], "to")) {
3391 if (*(args[1]) == 0) {
3392 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3393 file, linenum, args[1]);
3394 err_code |= ERR_ALERT | ERR_FATAL;
3395 goto out;
3396 }
3397 free(curproxy->email_alert.to);
3398 curproxy->email_alert.to = strdup(args[2]);
3399 }
3400 else {
3401 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
3402 file, linenum, args[1]);
3403 err_code |= ERR_ALERT | ERR_FATAL;
3404 goto out;
3405 }
Simon Horman64e34162015-02-06 11:11:57 +09003406 /* Indicate that the email_alert is at least partially configured */
3407 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09003408 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09003409 else if (!strcmp(args[0], "external-check")) {
3410 if (*(args[1]) == 0) {
3411 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3412 file, linenum, args[0]);
3413 err_code |= ERR_ALERT | ERR_FATAL;
3414 goto out;
3415 }
3416
3417 if (!strcmp(args[1], "command")) {
William Lallemanddf1425a2015-04-28 20:17:49 +02003418 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3419 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09003420 if (*(args[1]) == 0) {
3421 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3422 file, linenum, args[1]);
3423 err_code |= ERR_ALERT | ERR_FATAL;
3424 goto out;
3425 }
3426 free(curproxy->check_command);
3427 curproxy->check_command = strdup(args[2]);
3428 }
3429 else if (!strcmp(args[1], "path")) {
William Lallemanddf1425a2015-04-28 20:17:49 +02003430 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3431 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09003432 if (*(args[1]) == 0) {
3433 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3434 file, linenum, args[1]);
3435 err_code |= ERR_ALERT | ERR_FATAL;
3436 goto out;
3437 }
3438 free(curproxy->check_path);
3439 curproxy->check_path = strdup(args[2]);
3440 }
3441 else {
3442 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
3443 file, linenum, args[1]);
3444 err_code |= ERR_ALERT | ERR_FATAL;
3445 goto out;
3446 }
3447 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02003448 else if (!strcmp(args[0], "persist")) { /* persist */
3449 if (*(args[1]) == 0) {
3450 Alert("parsing [%s:%d] : missing persist method.\n",
3451 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003452 err_code |= ERR_ALERT | ERR_FATAL;
3453 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003454 }
3455
3456 if (!strncmp(args[1], "rdp-cookie", 10)) {
3457 curproxy->options2 |= PR_O2_RDPC_PRST;
3458
Emeric Brunb982a3d2010-01-04 15:45:53 +01003459 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003460 const char *beg, *end;
3461
3462 beg = args[1] + 11;
3463 end = strchr(beg, ')');
3464
William Lallemanddf1425a2015-04-28 20:17:49 +02003465 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3466 goto out;
3467
Emeric Brun647caf12009-06-30 17:57:00 +02003468 if (!end || end == beg) {
3469 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3470 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003471 err_code |= ERR_ALERT | ERR_FATAL;
3472 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003473 }
3474
3475 free(curproxy->rdp_cookie_name);
3476 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3477 curproxy->rdp_cookie_len = end-beg;
3478 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003479 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003480 free(curproxy->rdp_cookie_name);
3481 curproxy->rdp_cookie_name = strdup("msts");
3482 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3483 }
3484 else { /* syntax */
3485 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3486 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003487 err_code |= ERR_ALERT | ERR_FATAL;
3488 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003489 }
3490 }
3491 else {
3492 Alert("parsing [%s:%d] : unknown persist method.\n",
3493 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003494 err_code |= ERR_ALERT | ERR_FATAL;
3495 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003496 }
3497 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003498 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreau6db62c52015-08-10 19:04:29 +02003499 Alert("parsing [%s:%d] : '%s' is not supported anymore, please check the documentation.\n", file, linenum, args[0]);
3500 err_code |= ERR_ALERT | ERR_FATAL;
3501 goto out;
3502 }
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02003503 else if (!strcmp(args[0], "load-server-state-from-file")) {
3504 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3505 err_code |= ERR_WARN;
3506 if (!strcmp(args[1], "global")) { /* use the file pointed to by global server-state-file directive */
3507 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_GLOBAL;
3508 }
3509 else if (!strcmp(args[1], "local")) { /* use the server-state-file-name variable to locate the server-state file */
3510 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_LOCAL;
3511 }
3512 else if (!strcmp(args[1], "none")) { /* don't use server-state-file directive for this backend */
3513 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
3514 }
3515 else {
3516 Alert("parsing [%s:%d] : '%s' expects 'global', 'local' or 'none'. Got '%s'\n",
3517 file, linenum, args[0], args[1]);
3518 err_code |= ERR_ALERT | ERR_FATAL;
3519 goto out;
3520 }
3521 }
3522 else if (!strcmp(args[0], "server-state-file-name")) {
3523 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3524 err_code |= ERR_WARN;
3525 if (*(args[1]) == 0) {
3526 Alert("parsing [%s:%d] : '%s' expects 'use-backend-name' or a string. Got no argument\n",
3527 file, linenum, args[0]);
3528 err_code |= ERR_ALERT | ERR_FATAL;
3529 goto out;
3530 }
3531 else if (!strcmp(args[1], "use-backend-name"))
3532 curproxy->server_state_file_name = strdup(curproxy->id);
3533 else
3534 curproxy->server_state_file_name = strdup(args[1]);
3535 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003536 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003537 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003538 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003539
Willy Tarreaubaaee002006-06-26 02:48:02 +02003540 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003541 if (curproxy == &defproxy) {
3542 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3543 err_code |= ERR_ALERT | ERR_FATAL;
3544 goto out;
3545 }
3546
William Lallemand1a748ae2015-05-19 16:37:23 +02003547 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3548 goto out;
3549
Willy Tarreaubaaee002006-06-26 02:48:02 +02003550 if (*(args[4]) == 0) {
3551 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3552 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003553 err_code |= ERR_ALERT | ERR_FATAL;
3554 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003555 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003556 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003557 curproxy->capture_name = strdup(args[2]);
3558 curproxy->capture_namelen = strlen(curproxy->capture_name);
3559 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003560 curproxy->to_log |= LW_COOKIE;
3561 }
3562 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3563 struct cap_hdr *hdr;
3564
3565 if (curproxy == &defproxy) {
3566 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 +02003567 err_code |= ERR_ALERT | ERR_FATAL;
3568 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003569 }
3570
William Lallemand1a748ae2015-05-19 16:37:23 +02003571 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3572 goto out;
3573
Willy Tarreaubaaee002006-06-26 02:48:02 +02003574 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3575 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3576 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003577 err_code |= ERR_ALERT | ERR_FATAL;
3578 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003579 }
3580
3581 hdr = calloc(sizeof(struct cap_hdr), 1);
3582 hdr->next = curproxy->req_cap;
3583 hdr->name = strdup(args[3]);
3584 hdr->namelen = strlen(args[3]);
3585 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003586 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003587 hdr->index = curproxy->nb_req_cap++;
3588 curproxy->req_cap = hdr;
3589 curproxy->to_log |= LW_REQHDR;
3590 }
3591 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3592 struct cap_hdr *hdr;
3593
3594 if (curproxy == &defproxy) {
3595 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 +02003596 err_code |= ERR_ALERT | ERR_FATAL;
3597 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003598 }
3599
William Lallemand1a748ae2015-05-19 16:37:23 +02003600 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3601 goto out;
3602
Willy Tarreaubaaee002006-06-26 02:48:02 +02003603 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3604 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3605 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003606 err_code |= ERR_ALERT | ERR_FATAL;
3607 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003608 }
3609 hdr = calloc(sizeof(struct cap_hdr), 1);
3610 hdr->next = curproxy->rsp_cap;
3611 hdr->name = strdup(args[3]);
3612 hdr->namelen = strlen(args[3]);
3613 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003614 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003615 hdr->index = curproxy->nb_rsp_cap++;
3616 curproxy->rsp_cap = hdr;
3617 curproxy->to_log |= LW_RSPHDR;
3618 }
3619 else {
3620 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3621 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003622 err_code |= ERR_ALERT | ERR_FATAL;
3623 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003624 }
3625 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003626 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003627 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003628 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003629
William Lallemanddf1425a2015-04-28 20:17:49 +02003630 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3631 goto out;
3632
Willy Tarreaubaaee002006-06-26 02:48:02 +02003633 if (*(args[1]) == 0) {
3634 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3635 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003636 err_code |= ERR_ALERT | ERR_FATAL;
3637 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003638 }
3639 curproxy->conn_retries = atol(args[1]);
3640 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003641 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003642 struct act_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003643
3644 if (curproxy == &defproxy) {
3645 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3646 err_code |= ERR_ALERT | ERR_FATAL;
3647 goto out;
3648 }
3649
Willy Tarreau20b0de52012-12-24 15:45:22 +01003650 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003651 !LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003652 (LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3653 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_DENY ||
3654 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REDIR ||
3655 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REQ_AUTH)) {
Willy Tarreau20b0de52012-12-24 15:45:22 +01003656 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 +01003657 file, linenum, args[0]);
3658 err_code |= ERR_WARN;
3659 }
3660
Willy Tarreauff011f22011-01-06 17:51:27 +01003661 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003662
Willy Tarreauff011f22011-01-06 17:51:27 +01003663 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003664 err_code |= ERR_ALERT | ERR_ABORT;
3665 goto out;
3666 }
3667
Willy Tarreau5002f572014-04-23 01:32:02 +02003668 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003669 err_code |= warnif_cond_conflicts(rule->cond,
3670 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3671 file, linenum);
3672
Willy Tarreauff011f22011-01-06 17:51:27 +01003673 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003674 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003675 else if (!strcmp(args[0], "http-response")) { /* response access control */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003676 struct act_rule *rule;
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003677
3678 if (curproxy == &defproxy) {
3679 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3680 err_code |= ERR_ALERT | ERR_FATAL;
3681 goto out;
3682 }
3683
3684 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003685 !LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003686 (LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3687 LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_DENY)) {
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003688 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3689 file, linenum, args[0]);
3690 err_code |= ERR_WARN;
3691 }
3692
3693 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3694
3695 if (!rule) {
3696 err_code |= ERR_ALERT | ERR_ABORT;
3697 goto out;
3698 }
3699
3700 err_code |= warnif_cond_conflicts(rule->cond,
3701 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3702 file, linenum);
3703
3704 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3705 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003706 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3707 /* set the header name and length into the proxy structure */
3708 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3709 err_code |= ERR_WARN;
3710
3711 if (!*args[1]) {
3712 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3713 file, linenum, args[0]);
3714 err_code |= ERR_ALERT | ERR_FATAL;
3715 goto out;
3716 }
3717
3718 /* set the desired header name */
3719 free(curproxy->server_id_hdr_name);
3720 curproxy->server_id_hdr_name = strdup(args[1]);
3721 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3722 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003723 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003724 struct act_rule *rule;
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003725
Willy Tarreaub099aca2008-10-12 17:26:37 +02003726 if (curproxy == &defproxy) {
3727 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003728 err_code |= ERR_ALERT | ERR_FATAL;
3729 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003730 }
3731
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003732 /* emulate "block" using "http-request block". Since these rules are supposed to
3733 * be processed before all http-request rules, we put them into their own list
3734 * and will insert them at the end.
3735 */
3736 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3737 if (!rule) {
3738 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003739 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003740 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003741 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3742 err_code |= warnif_cond_conflicts(rule->cond,
3743 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3744 file, linenum);
3745 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003746
3747 if (!already_warned(WARN_BLOCK_DEPRECATED))
3748 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]);
3749
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003750 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003751 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003752 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003753
Cyril Bonté99ed3272010-01-24 23:29:44 +01003754 if (curproxy == &defproxy) {
3755 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3756 err_code |= ERR_ALERT | ERR_FATAL;
3757 goto out;
3758 }
3759
Willy Tarreaube4653b2015-05-28 15:26:58 +02003760 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003761 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3762 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003763 err_code |= ERR_ALERT | ERR_FATAL;
3764 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003765 }
3766
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003767 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003768 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003769 err_code |= warnif_cond_conflicts(rule->cond,
3770 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3771 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003772 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003773 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003774 struct switching_rule *rule;
3775
Willy Tarreaub099aca2008-10-12 17:26:37 +02003776 if (curproxy == &defproxy) {
3777 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003778 err_code |= ERR_ALERT | ERR_FATAL;
3779 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003780 }
3781
Willy Tarreau55ea7572007-06-17 19:56:27 +02003782 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003783 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003784
3785 if (*(args[1]) == 0) {
3786 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003787 err_code |= ERR_ALERT | ERR_FATAL;
3788 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003789 }
3790
Willy Tarreauf51658d2014-04-23 01:21:56 +02003791 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3792 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3793 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3794 file, linenum, errmsg);
3795 err_code |= ERR_ALERT | ERR_FATAL;
3796 goto out;
3797 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003798
Willy Tarreauf51658d2014-04-23 01:21:56 +02003799 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003800 }
3801
3802 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
3803 rule->cond = cond;
3804 rule->be.name = strdup(args[1]);
3805 LIST_INIT(&rule->list);
3806 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3807 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003808 else if (strcmp(args[0], "use-server") == 0) {
3809 struct server_rule *rule;
3810
3811 if (curproxy == &defproxy) {
3812 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3813 err_code |= ERR_ALERT | ERR_FATAL;
3814 goto out;
3815 }
3816
3817 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3818 err_code |= ERR_WARN;
3819
3820 if (*(args[1]) == 0) {
3821 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3822 err_code |= ERR_ALERT | ERR_FATAL;
3823 goto out;
3824 }
3825
3826 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3827 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3828 file, linenum, args[0]);
3829 err_code |= ERR_ALERT | ERR_FATAL;
3830 goto out;
3831 }
3832
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003833 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3834 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3835 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003836 err_code |= ERR_ALERT | ERR_FATAL;
3837 goto out;
3838 }
3839
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003840 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003841
3842 rule = (struct server_rule *)calloc(1, sizeof(*rule));
3843 rule->cond = cond;
3844 rule->srv.name = strdup(args[1]);
3845 LIST_INIT(&rule->list);
3846 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3847 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3848 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003849 else if ((!strcmp(args[0], "force-persist")) ||
3850 (!strcmp(args[0], "ignore-persist"))) {
3851 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003852
3853 if (curproxy == &defproxy) {
3854 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3855 err_code |= ERR_ALERT | ERR_FATAL;
3856 goto out;
3857 }
3858
3859 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3860 err_code |= ERR_WARN;
3861
Willy Tarreauef6494c2010-01-28 17:12:36 +01003862 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003863 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3864 file, linenum, args[0]);
3865 err_code |= ERR_ALERT | ERR_FATAL;
3866 goto out;
3867 }
3868
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003869 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3870 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3871 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003872 err_code |= ERR_ALERT | ERR_FATAL;
3873 goto out;
3874 }
3875
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003876 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3877 * where force-persist is applied.
3878 */
3879 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003880
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003881 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003882 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003883 if (!strcmp(args[0], "force-persist")) {
3884 rule->type = PERSIST_TYPE_FORCE;
3885 } else {
3886 rule->type = PERSIST_TYPE_IGNORE;
3887 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003888 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003889 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003890 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003891 else if (!strcmp(args[0], "stick-table")) {
3892 int myidx = 1;
Willy Tarreaue45288c2015-05-26 10:49:46 +02003893 struct proxy *other;
3894
Willy Tarreaue2dc1fa2015-05-26 12:08:07 +02003895 other = proxy_tbl_by_name(curproxy->id);
Willy Tarreaue45288c2015-05-26 10:49:46 +02003896 if (other) {
3897 Alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
3898 file, linenum, curproxy->id, proxy_type_str(other), other->id, other->conf.file, other->conf.line);
3899 err_code |= ERR_ALERT | ERR_FATAL;
3900 goto out;
3901 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003902
Emeric Brun32da3c42010-09-23 18:39:19 +02003903 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003904 curproxy->table.type = (unsigned int)-1;
3905 while (*args[myidx]) {
3906 const char *err;
3907
3908 if (strcmp(args[myidx], "size") == 0) {
3909 myidx++;
3910 if (!*(args[myidx])) {
3911 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3912 file, linenum, args[myidx-1]);
3913 err_code |= ERR_ALERT | ERR_FATAL;
3914 goto out;
3915 }
3916 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3917 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3918 file, linenum, *err, args[myidx-1]);
3919 err_code |= ERR_ALERT | ERR_FATAL;
3920 goto out;
3921 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003922 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003923 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003924 else if (strcmp(args[myidx], "peers") == 0) {
3925 myidx++;
Godbach50523162013-12-11 19:48:57 +08003926 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003927 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3928 file, linenum, args[myidx-1]);
3929 err_code |= ERR_ALERT | ERR_FATAL;
3930 goto out;
Godbach50523162013-12-11 19:48:57 +08003931 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003932 curproxy->table.peers.name = strdup(args[myidx++]);
3933 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003934 else if (strcmp(args[myidx], "expire") == 0) {
3935 myidx++;
3936 if (!*(args[myidx])) {
3937 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3938 file, linenum, args[myidx-1]);
3939 err_code |= ERR_ALERT | ERR_FATAL;
3940 goto out;
3941 }
3942 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3943 if (err) {
3944 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3945 file, linenum, *err, args[myidx-1]);
3946 err_code |= ERR_ALERT | ERR_FATAL;
3947 goto out;
3948 }
3949 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003950 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003951 }
3952 else if (strcmp(args[myidx], "nopurge") == 0) {
3953 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003954 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003955 }
3956 else if (strcmp(args[myidx], "type") == 0) {
3957 myidx++;
3958 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3959 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3960 file, linenum, args[myidx]);
3961 err_code |= ERR_ALERT | ERR_FATAL;
3962 goto out;
3963 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003964 /* myidx already points to next arg */
3965 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003966 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003967 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003968 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003969
3970 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003971 nw = args[myidx];
3972 while (*nw) {
3973 /* the "store" keyword supports a comma-separated list */
3974 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003975 sa = NULL; /* store arg */
3976 while (*nw && *nw != ',') {
3977 if (*nw == '(') {
3978 *nw = 0;
3979 sa = ++nw;
3980 while (*nw != ')') {
3981 if (!*nw) {
3982 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3983 file, linenum, args[0], cw);
3984 err_code |= ERR_ALERT | ERR_FATAL;
3985 goto out;
3986 }
3987 nw++;
3988 }
3989 *nw = '\0';
3990 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003991 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003992 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003993 if (*nw)
3994 *nw++ = '\0';
3995 type = stktable_get_data_type(cw);
3996 if (type < 0) {
3997 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3998 file, linenum, args[0], cw);
3999 err_code |= ERR_ALERT | ERR_FATAL;
4000 goto out;
4001 }
Willy Tarreauac782882010-06-20 10:41:54 +02004002
4003 err = stktable_alloc_data_type(&curproxy->table, type, sa);
4004 switch (err) {
4005 case PE_NONE: break;
4006 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004007 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
4008 file, linenum, args[0], cw);
4009 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02004010 break;
4011
4012 case PE_ARG_MISSING:
4013 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
4014 file, linenum, args[0], cw);
4015 err_code |= ERR_ALERT | ERR_FATAL;
4016 goto out;
4017
4018 case PE_ARG_NOT_USED:
4019 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
4020 file, linenum, args[0], cw);
4021 err_code |= ERR_ALERT | ERR_FATAL;
4022 goto out;
4023
4024 default:
4025 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
4026 file, linenum, args[0], cw);
4027 err_code |= ERR_ALERT | ERR_FATAL;
4028 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004029 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004030 }
4031 myidx++;
4032 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004033 else {
4034 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
4035 file, linenum, args[myidx]);
4036 err_code |= ERR_ALERT | ERR_FATAL;
4037 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004038 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004039 }
4040
4041 if (!curproxy->table.size) {
4042 Alert("parsing [%s:%d] : stick-table: missing size.\n",
4043 file, linenum);
4044 err_code |= ERR_ALERT | ERR_FATAL;
4045 goto out;
4046 }
4047
4048 if (curproxy->table.type == (unsigned int)-1) {
4049 Alert("parsing [%s:%d] : stick-table: missing type.\n",
4050 file, linenum);
4051 err_code |= ERR_ALERT | ERR_FATAL;
4052 goto out;
4053 }
4054 }
4055 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004056 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02004057 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004058 int myidx = 0;
4059 const char *name = NULL;
4060 int flags;
4061
4062 if (curproxy == &defproxy) {
4063 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4064 err_code |= ERR_ALERT | ERR_FATAL;
4065 goto out;
4066 }
4067
4068 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
4069 err_code |= ERR_WARN;
4070 goto out;
4071 }
4072
4073 myidx++;
4074 if ((strcmp(args[myidx], "store") == 0) ||
4075 (strcmp(args[myidx], "store-request") == 0)) {
4076 myidx++;
4077 flags = STK_IS_STORE;
4078 }
4079 else if (strcmp(args[myidx], "store-response") == 0) {
4080 myidx++;
4081 flags = STK_IS_STORE | STK_ON_RSP;
4082 }
4083 else if (strcmp(args[myidx], "match") == 0) {
4084 myidx++;
4085 flags = STK_IS_MATCH;
4086 }
4087 else if (strcmp(args[myidx], "on") == 0) {
4088 myidx++;
4089 flags = STK_IS_MATCH | STK_IS_STORE;
4090 }
4091 else {
4092 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
4093 err_code |= ERR_ALERT | ERR_FATAL;
4094 goto out;
4095 }
4096
4097 if (*(args[myidx]) == 0) {
4098 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
4099 err_code |= ERR_ALERT | ERR_FATAL;
4100 goto out;
4101 }
4102
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004103 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01004104 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004105 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01004106 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004107 err_code |= ERR_ALERT | ERR_FATAL;
4108 goto out;
4109 }
4110
4111 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01004112 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
4113 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
4114 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004115 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004116 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004117 goto out;
4118 }
4119 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01004120 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
4121 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
4122 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004123 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004124 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004125 goto out;
4126 }
4127 }
4128
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004129 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01004130 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004131
Emeric Brunb982a3d2010-01-04 15:45:53 +01004132 if (strcmp(args[myidx], "table") == 0) {
4133 myidx++;
4134 name = args[myidx++];
4135 }
4136
Willy Tarreauef6494c2010-01-28 17:12:36 +01004137 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004138 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
4139 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
4140 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004141 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004142 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004143 goto out;
4144 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004145 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01004146 else if (*(args[myidx])) {
4147 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
4148 file, linenum, args[0], args[myidx]);
4149 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004150 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01004151 goto out;
4152 }
Emeric Brun97679e72010-09-23 17:56:44 +02004153 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004154 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02004155 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004156 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01004157
Emeric Brunb982a3d2010-01-04 15:45:53 +01004158 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
4159 rule->cond = cond;
4160 rule->expr = expr;
4161 rule->flags = flags;
4162 rule->table.name = name ? strdup(name) : NULL;
4163 LIST_INIT(&rule->list);
4164 if (flags & STK_ON_RSP)
4165 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
4166 else
4167 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
4168 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004169 else if (!strcmp(args[0], "stats")) {
4170 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
4171 curproxy->uri_auth = NULL; /* we must detach from the default config */
4172
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004173 if (!*args[1]) {
4174 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02004175 } else if (!strcmp(args[1], "admin")) {
4176 struct stats_admin_rule *rule;
4177
4178 if (curproxy == &defproxy) {
4179 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
4180 err_code |= ERR_ALERT | ERR_FATAL;
4181 goto out;
4182 }
4183
4184 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4185 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4186 err_code |= ERR_ALERT | ERR_ABORT;
4187 goto out;
4188 }
4189
4190 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4191 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4192 file, linenum, args[0], args[1]);
4193 err_code |= ERR_ALERT | ERR_FATAL;
4194 goto out;
4195 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004196 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4197 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
4198 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02004199 err_code |= ERR_ALERT | ERR_FATAL;
4200 goto out;
4201 }
4202
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004203 err_code |= warnif_cond_conflicts(cond,
4204 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4205 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02004206
4207 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
4208 rule->cond = cond;
4209 LIST_INIT(&rule->list);
4210 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004211 } else if (!strcmp(args[1], "uri")) {
4212 if (*(args[2]) == 0) {
4213 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004214 err_code |= ERR_ALERT | ERR_FATAL;
4215 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004216 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
4217 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004218 err_code |= ERR_ALERT | ERR_ABORT;
4219 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004220 }
4221 } else if (!strcmp(args[1], "realm")) {
4222 if (*(args[2]) == 0) {
4223 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004224 err_code |= ERR_ALERT | ERR_FATAL;
4225 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004226 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
4227 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004228 err_code |= ERR_ALERT | ERR_ABORT;
4229 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004230 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02004231 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004232 unsigned interval;
4233
4234 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
4235 if (err) {
4236 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
4237 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004238 err_code |= ERR_ALERT | ERR_FATAL;
4239 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004240 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
4241 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004242 err_code |= ERR_ALERT | ERR_ABORT;
4243 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004244 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004245 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004246 struct act_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004247
4248 if (curproxy == &defproxy) {
4249 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4250 err_code |= ERR_ALERT | ERR_FATAL;
4251 goto out;
4252 }
4253
4254 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4255 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4256 err_code |= ERR_ALERT | ERR_ABORT;
4257 goto out;
4258 }
4259
Willy Tarreauff011f22011-01-06 17:51:27 +01004260 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004261 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct act_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004262 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
4263 file, linenum, args[0]);
4264 err_code |= ERR_WARN;
4265 }
4266
Willy Tarreauff011f22011-01-06 17:51:27 +01004267 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004268
Willy Tarreauff011f22011-01-06 17:51:27 +01004269 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004270 err_code |= ERR_ALERT | ERR_ABORT;
4271 goto out;
4272 }
4273
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004274 err_code |= warnif_cond_conflicts(rule->cond,
4275 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4276 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01004277 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004278
Willy Tarreaubaaee002006-06-26 02:48:02 +02004279 } else if (!strcmp(args[1], "auth")) {
4280 if (*(args[2]) == 0) {
4281 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004282 err_code |= ERR_ALERT | ERR_FATAL;
4283 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004284 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
4285 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004286 err_code |= ERR_ALERT | ERR_ABORT;
4287 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004288 }
4289 } else if (!strcmp(args[1], "scope")) {
4290 if (*(args[2]) == 0) {
4291 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004292 err_code |= ERR_ALERT | ERR_FATAL;
4293 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004294 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
4295 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004296 err_code |= ERR_ALERT | ERR_ABORT;
4297 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004298 }
4299 } else if (!strcmp(args[1], "enable")) {
4300 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4301 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004302 err_code |= ERR_ALERT | ERR_ABORT;
4303 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004304 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004305 } else if (!strcmp(args[1], "hide-version")) {
4306 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
4307 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004308 err_code |= ERR_ALERT | ERR_ABORT;
4309 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004310 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01004311 } else if (!strcmp(args[1], "show-legends")) {
4312 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
4313 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4314 err_code |= ERR_ALERT | ERR_ABORT;
4315 goto out;
4316 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004317 } else if (!strcmp(args[1], "show-node")) {
4318
4319 if (*args[2]) {
4320 int i;
4321 char c;
4322
4323 for (i=0; args[2][i]; i++) {
4324 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01004325 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
4326 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004327 break;
4328 }
4329
4330 if (!i || args[2][i]) {
4331 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
4332 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
4333 file, linenum, args[0], args[1]);
4334 err_code |= ERR_ALERT | ERR_FATAL;
4335 goto out;
4336 }
4337 }
4338
4339 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
4340 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4341 err_code |= ERR_ALERT | ERR_ABORT;
4342 goto out;
4343 }
4344 } else if (!strcmp(args[1], "show-desc")) {
4345 char *desc = NULL;
4346
4347 if (*args[2]) {
4348 int i, len=0;
4349 char *d;
4350
Willy Tarreau348acfe2014-04-14 15:00:39 +02004351 for (i = 2; *args[i]; i++)
4352 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004353
4354 desc = d = (char *)calloc(1, len);
4355
Willy Tarreau348acfe2014-04-14 15:00:39 +02004356 d += snprintf(d, desc + len - d, "%s", args[2]);
4357 for (i = 3; *args[i]; i++)
4358 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004359 }
4360
4361 if (!*args[2] && !global.desc)
4362 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
4363 file, linenum, args[1]);
4364 else {
4365 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
4366 free(desc);
4367 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4368 err_code |= ERR_ALERT | ERR_ABORT;
4369 goto out;
4370 }
4371 free(desc);
4372 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004373 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004374stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02004375 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 +01004376 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004377 err_code |= ERR_ALERT | ERR_FATAL;
4378 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004379 }
4380 }
4381 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004382 int optnum;
4383
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004384 if (*(args[1]) == '\0') {
4385 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
4386 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004387 err_code |= ERR_ALERT | ERR_FATAL;
4388 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004389 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01004390
4391 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
4392 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004393 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
4394 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4395 file, linenum, cfg_opts[optnum].name);
4396 err_code |= ERR_ALERT | ERR_FATAL;
4397 goto out;
4398 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004399 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4400 goto out;
4401
Willy Tarreau93893792009-07-23 13:19:11 +02004402 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
4403 err_code |= ERR_WARN;
4404 goto out;
4405 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004406
Willy Tarreau3842f002009-06-14 11:39:52 +02004407 curproxy->no_options &= ~cfg_opts[optnum].val;
4408 curproxy->options &= ~cfg_opts[optnum].val;
4409
4410 switch (kwm) {
4411 case KWM_STD:
4412 curproxy->options |= cfg_opts[optnum].val;
4413 break;
4414 case KWM_NO:
4415 curproxy->no_options |= cfg_opts[optnum].val;
4416 break;
4417 case KWM_DEF: /* already cleared */
4418 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004419 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004420
Willy Tarreau93893792009-07-23 13:19:11 +02004421 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004422 }
4423 }
4424
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004425 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
4426 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004427 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
4428 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4429 file, linenum, cfg_opts2[optnum].name);
4430 err_code |= ERR_ALERT | ERR_FATAL;
4431 goto out;
4432 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004433 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4434 goto out;
Willy Tarreau93893792009-07-23 13:19:11 +02004435 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4436 err_code |= ERR_WARN;
4437 goto out;
4438 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004439
Willy Tarreau3842f002009-06-14 11:39:52 +02004440 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4441 curproxy->options2 &= ~cfg_opts2[optnum].val;
4442
4443 switch (kwm) {
4444 case KWM_STD:
4445 curproxy->options2 |= cfg_opts2[optnum].val;
4446 break;
4447 case KWM_NO:
4448 curproxy->no_options2 |= cfg_opts2[optnum].val;
4449 break;
4450 case KWM_DEF: /* already cleared */
4451 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004452 }
Willy Tarreau93893792009-07-23 13:19:11 +02004453 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004454 }
4455 }
4456
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004457 /* HTTP options override each other. They can be cancelled using
4458 * "no option xxx" which only switches to default mode if the mode
4459 * was this one (useful for cancelling options set in defaults
4460 * sections).
4461 */
4462 if (strcmp(args[1], "httpclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004463 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4464 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004465 if (kwm == KWM_STD) {
4466 curproxy->options &= ~PR_O_HTTP_MODE;
4467 curproxy->options |= PR_O_HTTP_PCL;
4468 goto out;
4469 }
4470 else if (kwm == KWM_NO) {
4471 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4472 curproxy->options &= ~PR_O_HTTP_MODE;
4473 goto out;
4474 }
4475 }
4476 else if (strcmp(args[1], "forceclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004477 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4478 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004479 if (kwm == KWM_STD) {
4480 curproxy->options &= ~PR_O_HTTP_MODE;
4481 curproxy->options |= PR_O_HTTP_FCL;
4482 goto out;
4483 }
4484 else if (kwm == KWM_NO) {
4485 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4486 curproxy->options &= ~PR_O_HTTP_MODE;
4487 goto out;
4488 }
4489 }
4490 else if (strcmp(args[1], "http-server-close") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004491 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4492 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004493 if (kwm == KWM_STD) {
4494 curproxy->options &= ~PR_O_HTTP_MODE;
4495 curproxy->options |= PR_O_HTTP_SCL;
4496 goto out;
4497 }
4498 else if (kwm == KWM_NO) {
4499 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4500 curproxy->options &= ~PR_O_HTTP_MODE;
4501 goto out;
4502 }
4503 }
4504 else if (strcmp(args[1], "http-keep-alive") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004505 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4506 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004507 if (kwm == KWM_STD) {
4508 curproxy->options &= ~PR_O_HTTP_MODE;
4509 curproxy->options |= PR_O_HTTP_KAL;
4510 goto out;
4511 }
4512 else if (kwm == KWM_NO) {
4513 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4514 curproxy->options &= ~PR_O_HTTP_MODE;
4515 goto out;
4516 }
4517 }
4518 else if (strcmp(args[1], "http-tunnel") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004519 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4520 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004521 if (kwm == KWM_STD) {
4522 curproxy->options &= ~PR_O_HTTP_MODE;
4523 curproxy->options |= PR_O_HTTP_TUN;
4524 goto out;
4525 }
4526 else if (kwm == KWM_NO) {
4527 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4528 curproxy->options &= ~PR_O_HTTP_MODE;
4529 goto out;
4530 }
4531 }
4532
Joseph Lynch726ab712015-05-11 23:25:34 -07004533 /* Redispatch can take an integer argument that control when the
4534 * resispatch occurs. All values are relative to the retries option.
4535 * This can be cancelled using "no option xxx".
4536 */
4537 if (strcmp(args[1], "redispatch") == 0) {
4538 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
4539 err_code |= ERR_WARN;
4540 goto out;
4541 }
4542
4543 curproxy->no_options &= ~PR_O_REDISP;
4544 curproxy->options &= ~PR_O_REDISP;
4545
4546 switch (kwm) {
4547 case KWM_STD:
4548 curproxy->options |= PR_O_REDISP;
4549 curproxy->redispatch_after = -1;
4550 if(*args[2]) {
4551 curproxy->redispatch_after = atol(args[2]);
4552 }
4553 break;
4554 case KWM_NO:
4555 curproxy->no_options |= PR_O_REDISP;
4556 curproxy->redispatch_after = 0;
4557 break;
4558 case KWM_DEF: /* already cleared */
4559 break;
4560 }
4561 goto out;
4562 }
4563
Willy Tarreau3842f002009-06-14 11:39:52 +02004564 if (kwm != KWM_STD) {
4565 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004566 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004567 err_code |= ERR_ALERT | ERR_FATAL;
4568 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004569 }
4570
Emeric Brun3a058f32009-06-30 18:26:00 +02004571 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004572 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004573 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004574 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004575 if (*(args[2]) != '\0') {
4576 if (!strcmp(args[2], "clf")) {
4577 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004578 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004579 } else {
William Lallemand77063bc2015-05-28 18:02:48 +02004580 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004581 err_code |= ERR_ALERT | ERR_FATAL;
4582 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004583 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004584 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
4585 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004586 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004587 if (curproxy->conf.logformat_string != default_http_log_format &&
4588 curproxy->conf.logformat_string != default_tcp_log_format &&
4589 curproxy->conf.logformat_string != clf_http_log_format)
4590 free(curproxy->conf.logformat_string);
4591 curproxy->conf.logformat_string = logformat;
4592
4593 free(curproxy->conf.lfs_file);
4594 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4595 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004596 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004597 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004598 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004599 if (curproxy->conf.logformat_string != default_http_log_format &&
4600 curproxy->conf.logformat_string != default_tcp_log_format &&
4601 curproxy->conf.logformat_string != clf_http_log_format)
4602 free(curproxy->conf.logformat_string);
4603 curproxy->conf.logformat_string = default_tcp_log_format;
4604
4605 free(curproxy->conf.lfs_file);
4606 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4607 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemanddf1425a2015-04-28 20:17:49 +02004608
4609 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4610 goto out;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004611 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004612 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004613 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004614 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004615 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004616
William Lallemanddf1425a2015-04-28 20:17:49 +02004617 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4618 goto out;
4619
Willy Tarreau13943ab2006-12-31 00:24:10 +01004620 if (curproxy->cap & PR_CAP_FE)
4621 curproxy->options |= PR_O_TCP_CLI_KA;
4622 if (curproxy->cap & PR_CAP_BE)
4623 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004624 }
4625 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004626 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004627 err_code |= ERR_WARN;
4628
Willy Tarreaubaaee002006-06-26 02:48:02 +02004629 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004630 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004631 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004632 curproxy->options2 &= ~PR_O2_CHK_ANY;
4633 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004634 if (!*args[2]) { /* no argument */
4635 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4636 curproxy->check_len = strlen(DEF_CHECK_REQ);
4637 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004638 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004639 curproxy->check_req = (char *)malloc(reqlen);
4640 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004641 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004642 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004643 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004644 if (*args[4])
4645 reqlen += strlen(args[4]);
4646 else
4647 reqlen += strlen("HTTP/1.0");
4648
4649 curproxy->check_req = (char *)malloc(reqlen);
4650 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004651 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004652 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004653 if (alertif_too_many_args_idx(3, 1, file, linenum, args, &err_code))
4654 goto out;
Willy Tarreauf3c69202006-07-09 16:42:34 +02004655 }
4656 else if (!strcmp(args[1], "ssl-hello-chk")) {
4657 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004658 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004659 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004660
Willy Tarreaua534fea2008-08-03 12:19:50 +02004661 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004662 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004663 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004664 curproxy->options2 |= PR_O2_SSL3_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004665
4666 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4667 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004668 }
Willy Tarreau23677902007-05-08 23:50:35 +02004669 else if (!strcmp(args[1], "smtpchk")) {
4670 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004671 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004672 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004673 curproxy->options2 &= ~PR_O2_CHK_ANY;
4674 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004675
4676 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4677 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4678 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4679 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4680 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4681 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
4682 curproxy->check_req = (char *)malloc(reqlen);
4683 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4684 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4685 } else {
4686 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4687 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4688 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4689 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4690 }
4691 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004692 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4693 goto out;
Willy Tarreau23677902007-05-08 23:50:35 +02004694 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004695 else if (!strcmp(args[1], "pgsql-check")) {
4696 /* use PostgreSQL request to check servers' health */
4697 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4698 err_code |= ERR_WARN;
4699
4700 free(curproxy->check_req);
4701 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004702 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004703 curproxy->options2 |= PR_O2_PGSQL_CHK;
4704
4705 if (*(args[2])) {
4706 int cur_arg = 2;
4707
4708 while (*(args[cur_arg])) {
4709 if (strcmp(args[cur_arg], "user") == 0) {
4710 char * packet;
4711 uint32_t packet_len;
4712 uint32_t pv;
4713
4714 /* suboption header - needs additional argument for it */
4715 if (*(args[cur_arg+1]) == 0) {
4716 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4717 file, linenum, args[0], args[1], args[cur_arg]);
4718 err_code |= ERR_ALERT | ERR_FATAL;
4719 goto out;
4720 }
4721
4722 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4723 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4724 pv = htonl(0x30000); /* protocol version 3.0 */
4725
4726 packet = (char*) calloc(1, packet_len);
4727
4728 memcpy(packet + 4, &pv, 4);
4729
4730 /* copy "user" */
4731 memcpy(packet + 8, "user", 4);
4732
4733 /* copy username */
4734 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4735
4736 free(curproxy->check_req);
4737 curproxy->check_req = packet;
4738 curproxy->check_len = packet_len;
4739
4740 packet_len = htonl(packet_len);
4741 memcpy(packet, &packet_len, 4);
4742 cur_arg += 2;
4743 } else {
4744 /* unknown suboption - catchall */
4745 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4746 file, linenum, args[0], args[1]);
4747 err_code |= ERR_ALERT | ERR_FATAL;
4748 goto out;
4749 }
4750 } /* end while loop */
4751 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004752 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4753 goto out;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004754 }
4755
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004756 else if (!strcmp(args[1], "redis-check")) {
4757 /* use REDIS PING request to check servers' health */
4758 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4759 err_code |= ERR_WARN;
4760
4761 free(curproxy->check_req);
4762 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004763 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004764 curproxy->options2 |= PR_O2_REDIS_CHK;
4765
4766 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
4767 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4768 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004769
4770 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4771 goto out;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004772 }
4773
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004774 else if (!strcmp(args[1], "mysql-check")) {
4775 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004776 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4777 err_code |= ERR_WARN;
4778
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004779 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004780 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004781 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004782 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004783
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004784 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004785 * const char mysql40_client_auth_pkt[] = {
4786 * "\x0e\x00\x00" // packet length
4787 * "\x01" // packet number
4788 * "\x00\x00" // client capabilities
4789 * "\x00\x00\x01" // max packet
4790 * "haproxy\x00" // username (null terminated string)
4791 * "\x00" // filler (always 0x00)
4792 * "\x01\x00\x00" // packet length
4793 * "\x00" // packet number
4794 * "\x01" // COM_QUIT command
4795 * };
4796 */
4797
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004798 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4799 * const char mysql41_client_auth_pkt[] = {
4800 * "\x0e\x00\x00\" // packet length
4801 * "\x01" // packet number
4802 * "\x00\x00\x00\x00" // client capabilities
4803 * "\x00\x00\x00\x01" // max packet
4804 * "\x21" // character set (UTF-8)
4805 * char[23] // All zeroes
4806 * "haproxy\x00" // username (null terminated string)
4807 * "\x00" // filler (always 0x00)
4808 * "\x01\x00\x00" // packet length
4809 * "\x00" // packet number
4810 * "\x01" // COM_QUIT command
4811 * };
4812 */
4813
4814
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004815 if (*(args[2])) {
4816 int cur_arg = 2;
4817
4818 while (*(args[cur_arg])) {
4819 if (strcmp(args[cur_arg], "user") == 0) {
4820 char *mysqluser;
4821 int packetlen, reqlen, userlen;
4822
4823 /* suboption header - needs additional argument for it */
4824 if (*(args[cur_arg+1]) == 0) {
4825 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4826 file, linenum, args[0], args[1], args[cur_arg]);
4827 err_code |= ERR_ALERT | ERR_FATAL;
4828 goto out;
4829 }
4830 mysqluser = args[cur_arg + 1];
4831 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004832
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004833 if (*(args[cur_arg+2])) {
4834 if (!strcmp(args[cur_arg+2], "post-41")) {
4835 packetlen = userlen + 7 + 27;
4836 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004837
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004838 free(curproxy->check_req);
4839 curproxy->check_req = (char *)calloc(1, reqlen);
4840 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004841
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004842 snprintf(curproxy->check_req, 4, "%c%c%c",
4843 ((unsigned char) packetlen & 0xff),
4844 ((unsigned char) (packetlen >> 8) & 0xff),
4845 ((unsigned char) (packetlen >> 16) & 0xff));
4846
4847 curproxy->check_req[3] = 1;
4848 curproxy->check_req[5] = 130;
4849 curproxy->check_req[11] = 1;
4850 curproxy->check_req[12] = 33;
4851 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4852 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4853 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4854 cur_arg += 3;
4855 } else {
4856 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4857 err_code |= ERR_ALERT | ERR_FATAL;
4858 goto out;
4859 }
4860 } else {
4861 packetlen = userlen + 7;
4862 reqlen = packetlen + 9;
4863
4864 free(curproxy->check_req);
4865 curproxy->check_req = (char *)calloc(1, reqlen);
4866 curproxy->check_len = reqlen;
4867
4868 snprintf(curproxy->check_req, 4, "%c%c%c",
4869 ((unsigned char) packetlen & 0xff),
4870 ((unsigned char) (packetlen >> 8) & 0xff),
4871 ((unsigned char) (packetlen >> 16) & 0xff));
4872
4873 curproxy->check_req[3] = 1;
4874 curproxy->check_req[5] = 128;
4875 curproxy->check_req[8] = 1;
4876 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4877 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4878 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4879 cur_arg += 2;
4880 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004881 } else {
4882 /* unknown suboption - catchall */
4883 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4884 file, linenum, args[0], args[1]);
4885 err_code |= ERR_ALERT | ERR_FATAL;
4886 goto out;
4887 }
4888 } /* end while loop */
4889 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004890 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004891 else if (!strcmp(args[1], "ldap-check")) {
4892 /* use LDAP request to check servers' health */
4893 free(curproxy->check_req);
4894 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004895 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004896 curproxy->options2 |= PR_O2_LDAP_CHK;
4897
4898 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
4899 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
4900 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004901 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4902 goto out;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004903 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004904 else if (!strcmp(args[1], "tcp-check")) {
4905 /* use raw TCPCHK send/expect to check servers' health */
4906 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4907 err_code |= ERR_WARN;
4908
4909 free(curproxy->check_req);
4910 curproxy->check_req = NULL;
4911 curproxy->options2 &= ~PR_O2_CHK_ANY;
4912 curproxy->options2 |= PR_O2_TCPCHK_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004913 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4914 goto out;
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004915 }
Simon Horman98637e52014-06-20 12:30:16 +09004916 else if (!strcmp(args[1], "external-check")) {
4917 /* excute an external command to check servers' health */
4918 free(curproxy->check_req);
4919 curproxy->check_req = NULL;
4920 curproxy->options2 &= ~PR_O2_CHK_ANY;
4921 curproxy->options2 |= PR_O2_EXT_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004922 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4923 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09004924 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004925 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004926 int cur_arg;
4927
4928 /* insert x-forwarded-for field, but not for the IP address listed as an except.
4929 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004930 */
Ross Westaf72a1d2008-08-03 10:51:45 +02004931
Willy Tarreau87cf5142011-08-19 22:57:24 +02004932 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02004933
4934 free(curproxy->fwdfor_hdr_name);
4935 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
4936 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
4937
4938 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
4939 cur_arg = 2;
4940 while (*(args[cur_arg])) {
4941 if (!strcmp(args[cur_arg], "except")) {
4942 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004943 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004944 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4945 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004946 err_code |= ERR_ALERT | ERR_FATAL;
4947 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004948 }
4949 /* flush useless bits */
4950 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02004951 cur_arg += 2;
4952 } else if (!strcmp(args[cur_arg], "header")) {
4953 /* suboption header - needs additional argument for it */
4954 if (*(args[cur_arg+1]) == 0) {
4955 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4956 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004957 err_code |= ERR_ALERT | ERR_FATAL;
4958 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02004959 }
4960 free(curproxy->fwdfor_hdr_name);
4961 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
4962 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
4963 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02004964 } else if (!strcmp(args[cur_arg], "if-none")) {
4965 curproxy->options &= ~PR_O_FF_ALWAYS;
4966 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004967 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02004968 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02004969 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02004970 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004971 err_code |= ERR_ALERT | ERR_FATAL;
4972 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004973 }
Ross Westaf72a1d2008-08-03 10:51:45 +02004974 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004975 }
Maik Broemme2850cb42009-04-17 18:53:21 +02004976 else if (!strcmp(args[1], "originalto")) {
4977 int cur_arg;
4978
4979 /* insert x-original-to field, but not for the IP address listed as an except.
4980 * set default options (ie: bitfield, header name, etc)
4981 */
4982
4983 curproxy->options |= PR_O_ORGTO;
4984
4985 free(curproxy->orgto_hdr_name);
4986 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
4987 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
4988
Willy Tarreau87cf5142011-08-19 22:57:24 +02004989 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02004990 cur_arg = 2;
4991 while (*(args[cur_arg])) {
4992 if (!strcmp(args[cur_arg], "except")) {
4993 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004994 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 +02004995 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4996 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004997 err_code |= ERR_ALERT | ERR_FATAL;
4998 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004999 }
5000 /* flush useless bits */
5001 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
5002 cur_arg += 2;
5003 } else if (!strcmp(args[cur_arg], "header")) {
5004 /* suboption header - needs additional argument for it */
5005 if (*(args[cur_arg+1]) == 0) {
5006 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5007 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005008 err_code |= ERR_ALERT | ERR_FATAL;
5009 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005010 }
5011 free(curproxy->orgto_hdr_name);
5012 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
5013 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
5014 cur_arg += 2;
5015 } else {
5016 /* unknown suboption - catchall */
5017 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
5018 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005019 err_code |= ERR_ALERT | ERR_FATAL;
5020 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005021 }
5022 } /* end while loop */
5023 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005024 else {
5025 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005026 err_code |= ERR_ALERT | ERR_FATAL;
5027 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005028 }
Willy Tarreau93893792009-07-23 13:19:11 +02005029 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005030 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005031 else if (!strcmp(args[0], "default_backend")) {
5032 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005033 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005034
5035 if (*(args[1]) == 0) {
5036 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005037 err_code |= ERR_ALERT | ERR_FATAL;
5038 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005039 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005040 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005041 curproxy->defbe.name = strdup(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005042
5043 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5044 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005045 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005046 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01005047 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005048 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005049
Willy Tarreaua3c504c2014-04-28 22:37:32 +02005050 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
5051 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 +01005052 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005053 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005054 /* enable reconnections to dispatch */
5055 curproxy->options |= PR_O_REDISP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005056
5057 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5058 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005059 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005060 else if (!strcmp(args[0], "http-reuse")) {
5061 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5062 err_code |= ERR_WARN;
5063
5064 if (strcmp(args[1], "never") == 0) {
5065 /* enable a graceful server shutdown on an HTTP 404 response */
5066 curproxy->options &= ~PR_O_REUSE_MASK;
5067 curproxy->options |= PR_O_REUSE_NEVR;
5068 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5069 goto out;
5070 }
Willy Tarreau161d45f2015-08-05 16:02:46 +02005071 else if (strcmp(args[1], "safe") == 0) {
5072 /* enable a graceful server shutdown on an HTTP 404 response */
5073 curproxy->options &= ~PR_O_REUSE_MASK;
5074 curproxy->options |= PR_O_REUSE_SAFE;
5075 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5076 goto out;
5077 }
Willy Tarreau449d74a2015-08-05 17:16:33 +02005078 else if (strcmp(args[1], "aggressive") == 0) {
5079 curproxy->options &= ~PR_O_REUSE_MASK;
5080 curproxy->options |= PR_O_REUSE_AGGR;
5081 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5082 goto out;
5083 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005084 else if (strcmp(args[1], "always") == 0) {
5085 /* enable a graceful server shutdown on an HTTP 404 response */
5086 curproxy->options &= ~PR_O_REUSE_MASK;
5087 curproxy->options |= PR_O_REUSE_ALWS;
5088 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5089 goto out;
5090 }
5091 else {
Willy Tarreau449d74a2015-08-05 17:16:33 +02005092 Alert("parsing [%s:%d] : '%s' only supports 'never', 'safe', 'aggressive', 'always'.\n", file, linenum, args[0]);
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005093 err_code |= ERR_ALERT | ERR_FATAL;
5094 goto out;
5095 }
5096 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005097 else if (!strcmp(args[0], "http-check")) {
5098 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005099 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01005100
5101 if (strcmp(args[1], "disable-on-404") == 0) {
5102 /* enable a graceful server shutdown on an HTTP 404 response */
5103 curproxy->options |= PR_O_DISABLE404;
William Lallemanddf1425a2015-04-28 20:17:49 +02005104 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5105 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005106 }
Willy Tarreauef781042010-01-27 11:53:01 +01005107 else if (strcmp(args[1], "send-state") == 0) {
5108 /* enable emission of the apparent state of a server in HTTP checks */
5109 curproxy->options2 |= PR_O2_CHK_SNDST;
William Lallemanddf1425a2015-04-28 20:17:49 +02005110 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5111 goto out;
Willy Tarreauef781042010-01-27 11:53:01 +01005112 }
Willy Tarreaubd741542010-03-16 18:46:54 +01005113 else if (strcmp(args[1], "expect") == 0) {
5114 const char *ptr_arg;
5115 int cur_arg;
5116
5117 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5118 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5119 err_code |= ERR_ALERT | ERR_FATAL;
5120 goto out;
5121 }
5122
5123 cur_arg = 2;
5124 /* consider exclamation marks, sole or at the beginning of a word */
5125 while (*(ptr_arg = args[cur_arg])) {
5126 while (*ptr_arg == '!') {
5127 curproxy->options2 ^= PR_O2_EXP_INV;
5128 ptr_arg++;
5129 }
5130 if (*ptr_arg)
5131 break;
5132 cur_arg++;
5133 }
5134 /* now ptr_arg points to the beginning of a word past any possible
5135 * exclamation mark, and cur_arg is the argument which holds this word.
5136 */
5137 if (strcmp(ptr_arg, "status") == 0) {
5138 if (!*(args[cur_arg + 1])) {
5139 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5140 file, linenum, args[0], args[1], ptr_arg);
5141 err_code |= ERR_ALERT | ERR_FATAL;
5142 goto out;
5143 }
5144 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005145 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005146 curproxy->expect_str = strdup(args[cur_arg + 1]);
5147 }
5148 else if (strcmp(ptr_arg, "string") == 0) {
5149 if (!*(args[cur_arg + 1])) {
5150 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5151 file, linenum, args[0], args[1], ptr_arg);
5152 err_code |= ERR_ALERT | ERR_FATAL;
5153 goto out;
5154 }
5155 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005156 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005157 curproxy->expect_str = strdup(args[cur_arg + 1]);
5158 }
5159 else if (strcmp(ptr_arg, "rstatus") == 0) {
5160 if (!*(args[cur_arg + 1])) {
5161 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5162 file, linenum, args[0], args[1], ptr_arg);
5163 err_code |= ERR_ALERT | ERR_FATAL;
5164 goto out;
5165 }
5166 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005167 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005168 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005169 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005170 free(curproxy->expect_regex);
5171 curproxy->expect_regex = NULL;
5172 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005173 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005174 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5175 error = NULL;
5176 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5177 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5178 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5179 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005180 err_code |= ERR_ALERT | ERR_FATAL;
5181 goto out;
5182 }
5183 }
5184 else if (strcmp(ptr_arg, "rstring") == 0) {
5185 if (!*(args[cur_arg + 1])) {
5186 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5187 file, linenum, args[0], args[1], ptr_arg);
5188 err_code |= ERR_ALERT | ERR_FATAL;
5189 goto out;
5190 }
5191 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005192 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005193 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005194 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005195 free(curproxy->expect_regex);
5196 curproxy->expect_regex = NULL;
5197 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005198 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005199 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5200 error = NULL;
5201 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5202 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5203 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5204 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005205 err_code |= ERR_ALERT | ERR_FATAL;
5206 goto out;
5207 }
5208 }
5209 else {
5210 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
5211 file, linenum, args[0], args[1], ptr_arg);
5212 err_code |= ERR_ALERT | ERR_FATAL;
5213 goto out;
5214 }
5215 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005216 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005217 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 +02005218 err_code |= ERR_ALERT | ERR_FATAL;
5219 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005220 }
5221 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005222 else if (!strcmp(args[0], "tcp-check")) {
5223 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5224 err_code |= ERR_WARN;
5225
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005226 if (strcmp(args[1], "comment") == 0) {
5227 int cur_arg;
5228 struct tcpcheck_rule *tcpcheck;
5229
5230 cur_arg = 1;
5231 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5232 tcpcheck->action = TCPCHK_ACT_COMMENT;
5233
5234 if (!*args[cur_arg + 1]) {
5235 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5236 file, linenum, args[cur_arg]);
5237 err_code |= ERR_ALERT | ERR_FATAL;
5238 goto out;
5239 }
5240
5241 tcpcheck->comment = strdup(args[cur_arg + 1]);
5242
5243 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
William Lallemanddf1425a2015-04-28 20:17:49 +02005244 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
5245 goto out;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005246 }
5247 else if (strcmp(args[1], "connect") == 0) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005248 const char *ptr_arg;
5249 int cur_arg;
5250 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005251
5252 /* check if first rule is also a 'connect' action */
Willy Tarreau5581c272015-05-13 12:24:53 +02005253 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
5254 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
5255 tcpcheck->action == TCPCHK_ACT_COMMENT) {
5256 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
5257 }
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005258
Willy Tarreau5581c272015-05-13 12:24:53 +02005259 if (&tcpcheck->list != &curproxy->tcpcheck_rules
5260 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
5261 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
5262 file, linenum);
5263 err_code |= ERR_ALERT | ERR_FATAL;
5264 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005265 }
5266
5267 cur_arg = 2;
5268 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5269 tcpcheck->action = TCPCHK_ACT_CONNECT;
5270
5271 /* parsing each parameters to fill up the rule */
5272 while (*(ptr_arg = args[cur_arg])) {
5273 /* tcp port */
5274 if (strcmp(args[cur_arg], "port") == 0) {
5275 if ( (atol(args[cur_arg + 1]) > 65535) ||
5276 (atol(args[cur_arg + 1]) < 1) ){
5277 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
5278 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
5279 err_code |= ERR_ALERT | ERR_FATAL;
5280 goto out;
5281 }
5282 tcpcheck->port = atol(args[cur_arg + 1]);
5283 cur_arg += 2;
5284 }
5285 /* send proxy protocol */
5286 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
5287 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
5288 cur_arg++;
5289 }
5290#ifdef USE_OPENSSL
5291 else if (strcmp(args[cur_arg], "ssl") == 0) {
5292 curproxy->options |= PR_O_TCPCHK_SSL;
5293 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
5294 cur_arg++;
5295 }
5296#endif /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005297 /* comment for this tcpcheck line */
5298 else if (strcmp(args[cur_arg], "comment") == 0) {
5299 if (!*args[cur_arg + 1]) {
5300 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5301 file, linenum, args[cur_arg]);
5302 err_code |= ERR_ALERT | ERR_FATAL;
5303 goto out;
5304 }
5305 tcpcheck->comment = strdup(args[cur_arg + 1]);
5306 cur_arg += 2;
5307 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005308 else {
5309#ifdef USE_OPENSSL
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005310 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 +01005311#else /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005312 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 +01005313#endif /* USE_OPENSSL */
5314 file, linenum, args[0], args[1], args[cur_arg]);
5315 err_code |= ERR_ALERT | ERR_FATAL;
5316 goto out;
5317 }
5318
5319 }
5320
5321 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5322 }
5323 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005324 if (! *(args[2]) ) {
5325 /* SEND string expected */
5326 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
5327 file, linenum, args[0], args[1], args[2]);
5328 err_code |= ERR_ALERT | ERR_FATAL;
5329 goto out;
5330 } else {
5331 struct tcpcheck_rule *tcpcheck;
5332
5333 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5334
5335 tcpcheck->action = TCPCHK_ACT_SEND;
5336 tcpcheck->string_len = strlen(args[2]);
5337 tcpcheck->string = strdup(args[2]);
5338 tcpcheck->expect_regex = NULL;
5339
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005340 /* comment for this tcpcheck line */
5341 if (strcmp(args[3], "comment") == 0) {
5342 if (!*args[4]) {
5343 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5344 file, linenum, args[3]);
5345 err_code |= ERR_ALERT | ERR_FATAL;
5346 goto out;
5347 }
5348 tcpcheck->comment = strdup(args[4]);
5349 }
5350
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005351 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5352 }
5353 }
5354 else if (strcmp(args[1], "send-binary") == 0) {
5355 if (! *(args[2]) ) {
5356 /* SEND binary string expected */
5357 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
5358 file, linenum, args[0], args[1], args[2]);
5359 err_code |= ERR_ALERT | ERR_FATAL;
5360 goto out;
5361 } else {
5362 struct tcpcheck_rule *tcpcheck;
5363 char *err = NULL;
5364
5365 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5366
5367 tcpcheck->action = TCPCHK_ACT_SEND;
5368 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5369 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5370 file, linenum, args[0], args[1], args[2], err);
5371 err_code |= ERR_ALERT | ERR_FATAL;
5372 goto out;
5373 }
5374 tcpcheck->expect_regex = NULL;
5375
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005376 /* comment for this tcpcheck line */
5377 if (strcmp(args[3], "comment") == 0) {
5378 if (!*args[4]) {
5379 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5380 file, linenum, args[3]);
5381 err_code |= ERR_ALERT | ERR_FATAL;
5382 goto out;
5383 }
5384 tcpcheck->comment = strdup(args[4]);
5385 }
5386
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005387 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5388 }
5389 }
5390 else if (strcmp(args[1], "expect") == 0) {
5391 const char *ptr_arg;
5392 int cur_arg;
5393 int inverse = 0;
5394
5395 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5396 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5397 err_code |= ERR_ALERT | ERR_FATAL;
5398 goto out;
5399 }
5400
5401 cur_arg = 2;
5402 /* consider exclamation marks, sole or at the beginning of a word */
5403 while (*(ptr_arg = args[cur_arg])) {
5404 while (*ptr_arg == '!') {
5405 inverse = !inverse;
5406 ptr_arg++;
5407 }
5408 if (*ptr_arg)
5409 break;
5410 cur_arg++;
5411 }
5412 /* now ptr_arg points to the beginning of a word past any possible
5413 * exclamation mark, and cur_arg is the argument which holds this word.
5414 */
5415 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005416 struct tcpcheck_rule *tcpcheck;
5417 char *err = NULL;
5418
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005419 if (!*(args[cur_arg + 1])) {
5420 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
5421 file, linenum, args[0], args[1], ptr_arg);
5422 err_code |= ERR_ALERT | ERR_FATAL;
5423 goto out;
5424 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005425
5426 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5427
5428 tcpcheck->action = TCPCHK_ACT_EXPECT;
5429 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5430 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5431 file, linenum, args[0], args[1], args[2], err);
5432 err_code |= ERR_ALERT | ERR_FATAL;
5433 goto out;
5434 }
5435 tcpcheck->expect_regex = NULL;
5436 tcpcheck->inverse = inverse;
5437
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005438 /* tcpcheck comment */
5439 cur_arg += 2;
5440 if (strcmp(args[cur_arg], "comment") == 0) {
5441 if (!*args[cur_arg + 1]) {
5442 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5443 file, linenum, args[cur_arg + 1]);
5444 err_code |= ERR_ALERT | ERR_FATAL;
5445 goto out;
5446 }
5447 tcpcheck->comment = strdup(args[cur_arg + 1]);
5448 }
5449
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005450 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5451 }
5452 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005453 struct tcpcheck_rule *tcpcheck;
5454
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005455 if (!*(args[cur_arg + 1])) {
5456 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5457 file, linenum, args[0], args[1], ptr_arg);
5458 err_code |= ERR_ALERT | ERR_FATAL;
5459 goto out;
5460 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005461
5462 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5463
5464 tcpcheck->action = TCPCHK_ACT_EXPECT;
5465 tcpcheck->string_len = strlen(args[cur_arg + 1]);
5466 tcpcheck->string = strdup(args[cur_arg + 1]);
5467 tcpcheck->expect_regex = NULL;
5468 tcpcheck->inverse = inverse;
5469
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005470 /* tcpcheck comment */
5471 cur_arg += 2;
5472 if (strcmp(args[cur_arg], "comment") == 0) {
5473 if (!*args[cur_arg + 1]) {
5474 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5475 file, linenum, args[cur_arg + 1]);
5476 err_code |= ERR_ALERT | ERR_FATAL;
5477 goto out;
5478 }
5479 tcpcheck->comment = strdup(args[cur_arg + 1]);
5480 }
5481
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005482 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5483 }
5484 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005485 struct tcpcheck_rule *tcpcheck;
5486
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005487 if (!*(args[cur_arg + 1])) {
5488 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5489 file, linenum, args[0], args[1], ptr_arg);
5490 err_code |= ERR_ALERT | ERR_FATAL;
5491 goto out;
5492 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005493
5494 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5495
5496 tcpcheck->action = TCPCHK_ACT_EXPECT;
5497 tcpcheck->string_len = 0;
5498 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005499 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
5500 error = NULL;
5501 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
5502 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5503 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5504 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005505 err_code |= ERR_ALERT | ERR_FATAL;
5506 goto out;
5507 }
5508 tcpcheck->inverse = inverse;
5509
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005510 /* tcpcheck comment */
5511 cur_arg += 2;
5512 if (strcmp(args[cur_arg], "comment") == 0) {
5513 if (!*args[cur_arg + 1]) {
5514 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5515 file, linenum, args[cur_arg + 1]);
5516 err_code |= ERR_ALERT | ERR_FATAL;
5517 goto out;
5518 }
5519 tcpcheck->comment = strdup(args[cur_arg + 1]);
5520 }
5521
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005522 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5523 }
5524 else {
5525 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
5526 file, linenum, args[0], args[1], ptr_arg);
5527 err_code |= ERR_ALERT | ERR_FATAL;
5528 goto out;
5529 }
5530 }
5531 else {
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005532 Alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005533 err_code |= ERR_ALERT | ERR_FATAL;
5534 goto out;
5535 }
5536 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01005537 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02005538 if (curproxy == &defproxy) {
5539 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005540 err_code |= ERR_ALERT | ERR_FATAL;
5541 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02005542 }
5543
Willy Tarreaub80c2302007-11-30 20:51:32 +01005544 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005545 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005546
5547 if (strcmp(args[1], "fail") == 0) {
5548 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01005549 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01005550 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
5551 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005552 err_code |= ERR_ALERT | ERR_FATAL;
5553 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005554 }
5555
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005556 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
5557 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
5558 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005559 err_code |= ERR_ALERT | ERR_FATAL;
5560 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005561 }
5562 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
5563 }
5564 else {
5565 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005566 err_code |= ERR_ALERT | ERR_FATAL;
5567 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005568 }
5569 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005570#ifdef TPROXY
5571 else if (!strcmp(args[0], "transparent")) {
5572 /* enable transparent proxy connections */
5573 curproxy->options |= PR_O_TRANSP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005574 if (alertif_too_many_args(0, file, linenum, args, &err_code))
5575 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005576 }
5577#endif
5578 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005579 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005580 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005581
Willy Tarreaubaaee002006-06-26 02:48:02 +02005582 if (*(args[1]) == 0) {
5583 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005584 err_code |= ERR_ALERT | ERR_FATAL;
5585 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005586 }
5587 curproxy->maxconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005588 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5589 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005590 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005591 else if (!strcmp(args[0], "backlog")) { /* backlog */
5592 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005593 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005594
5595 if (*(args[1]) == 0) {
5596 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005597 err_code |= ERR_ALERT | ERR_FATAL;
5598 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005599 }
5600 curproxy->backlog = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005601 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5602 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005603 }
Willy Tarreau86034312006-12-29 00:10:33 +01005604 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005605 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005606 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005607
Willy Tarreau86034312006-12-29 00:10:33 +01005608 if (*(args[1]) == 0) {
5609 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005610 err_code |= ERR_ALERT | ERR_FATAL;
5611 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005612 }
5613 curproxy->fullconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005614 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5615 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005616 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005617 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
5618 if (*(args[1]) == 0) {
5619 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005620 err_code |= ERR_ALERT | ERR_FATAL;
5621 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005622 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005623 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
5624 if (err) {
5625 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
5626 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02005627 err_code |= ERR_ALERT | ERR_FATAL;
5628 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005629 }
5630 curproxy->grace = val;
William Lallemanddf1425a2015-04-28 20:17:49 +02005631 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5632 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005633 }
5634 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01005635 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005636 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005637 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005638
Willy Tarreaubaaee002006-06-26 02:48:02 +02005639 if (curproxy == &defproxy) {
5640 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005641 err_code |= ERR_ALERT | ERR_FATAL;
5642 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005643 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005644 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005645 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005646
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02005647 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005648 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005649 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005650 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005651 goto out;
5652 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005653
5654 proto = protocol_by_family(sk->ss_family);
5655 if (!proto || !proto->connect) {
5656 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5657 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005658 err_code |= ERR_ALERT | ERR_FATAL;
5659 goto out;
5660 }
5661
5662 if (port1 != port2) {
5663 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5664 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005665 err_code |= ERR_ALERT | ERR_FATAL;
5666 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005667 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005668
5669 if (!port1) {
5670 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5671 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005672 err_code |= ERR_ALERT | ERR_FATAL;
5673 goto out;
5674 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005675
William Lallemanddf1425a2015-04-28 20:17:49 +02005676 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5677 goto out;
5678
Willy Tarreaud5191e72010-02-09 20:50:45 +01005679 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005680 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005681 }
5682 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005683 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005684 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005685
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005686 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5687 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005688 err_code |= ERR_ALERT | ERR_FATAL;
5689 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005690 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005691 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005692 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005693 /**
5694 * The syntax for hash-type config element is
5695 * hash-type {map-based|consistent} [[<algo>] avalanche]
5696 *
5697 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5698 */
5699 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005700
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005701 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5702 err_code |= ERR_WARN;
5703
5704 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005705 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5706 }
5707 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005708 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5709 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005710 else if (strcmp(args[1], "avalanche") == 0) {
5711 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]);
5712 err_code |= ERR_ALERT | ERR_FATAL;
5713 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005714 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005715 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005716 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005717 err_code |= ERR_ALERT | ERR_FATAL;
5718 goto out;
5719 }
Bhaskar98634f02013-10-29 23:30:51 -04005720
5721 /* set the hash function to use */
5722 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005723 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005724 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005725
5726 /* if consistent with no argument, then avalanche modifier is also applied */
5727 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5728 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005729 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005730 /* set the hash function */
5731 if (!strcmp(args[2], "sdbm")) {
5732 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5733 }
5734 else if (!strcmp(args[2], "djb2")) {
5735 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005736 }
5737 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005738 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005739 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005740 else if (!strcmp(args[2], "crc32")) {
5741 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5742 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005743 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005744 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 -05005745 err_code |= ERR_ALERT | ERR_FATAL;
5746 goto out;
5747 }
5748
5749 /* set the hash modifier */
5750 if (!strcmp(args[3], "avalanche")) {
5751 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5752 }
5753 else if (*args[3]) {
5754 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5755 err_code |= ERR_ALERT | ERR_FATAL;
5756 goto out;
5757 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005758 }
William Lallemanda73203e2012-03-12 12:48:57 +01005759 }
William Lallemanda73203e2012-03-12 12:48:57 +01005760 else if (strcmp(args[0], "unique-id-format") == 0) {
5761 if (!*(args[1])) {
5762 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5763 err_code |= ERR_ALERT | ERR_FATAL;
5764 goto out;
5765 }
William Lallemand3203ff42012-11-11 17:30:56 +01005766 if (*(args[2])) {
5767 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5768 err_code |= ERR_ALERT | ERR_FATAL;
5769 goto out;
5770 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005771 free(curproxy->conf.uniqueid_format_string);
5772 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005773
Willy Tarreau62a61232013-04-12 18:13:46 +02005774 free(curproxy->conf.uif_file);
5775 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5776 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005777 }
William Lallemanda73203e2012-03-12 12:48:57 +01005778
5779 else if (strcmp(args[0], "unique-id-header") == 0) {
5780 if (!*(args[1])) {
5781 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5782 err_code |= ERR_ALERT | ERR_FATAL;
5783 goto out;
5784 }
5785 free(curproxy->header_unique_id);
5786 curproxy->header_unique_id = strdup(args[1]);
5787 }
5788
William Lallemand723b73a2012-02-08 16:37:49 +01005789 else if (strcmp(args[0], "log-format") == 0) {
5790 if (!*(args[1])) {
5791 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5792 err_code |= ERR_ALERT | ERR_FATAL;
5793 goto out;
5794 }
William Lallemand3203ff42012-11-11 17:30:56 +01005795 if (*(args[2])) {
5796 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5797 err_code |= ERR_ALERT | ERR_FATAL;
5798 goto out;
5799 }
Willy Tarreau196729e2012-05-31 19:30:26 +02005800
Willy Tarreau62a61232013-04-12 18:13:46 +02005801 if (curproxy->conf.logformat_string != default_http_log_format &&
5802 curproxy->conf.logformat_string != default_tcp_log_format &&
5803 curproxy->conf.logformat_string != clf_http_log_format)
5804 free(curproxy->conf.logformat_string);
5805 curproxy->conf.logformat_string = strdup(args[1]);
5806
5807 free(curproxy->conf.lfs_file);
5808 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5809 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005810
5811 /* get a chance to improve log-format error reporting by
5812 * reporting the correct line-number when possible.
5813 */
5814 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5815 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5816 file, linenum, curproxy->id);
5817 err_code |= ERR_WARN;
5818 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005819 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02005820 else if (!strcmp(args[0], "log-format-sd")) {
5821 if (!*(args[1])) {
5822 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5823 err_code |= ERR_ALERT | ERR_FATAL;
5824 goto out;
5825 }
5826 if (*(args[2])) {
5827 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5828 err_code |= ERR_ALERT | ERR_FATAL;
5829 goto out;
5830 }
5831
5832 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
5833 free(curproxy->conf.logformat_sd_string);
5834 curproxy->conf.logformat_sd_string = strdup(args[1]);
5835
5836 free(curproxy->conf.lfsd_file);
5837 curproxy->conf.lfsd_file = strdup(curproxy->conf.args.file);
5838 curproxy->conf.lfsd_line = curproxy->conf.args.line;
5839
5840 /* get a chance to improve log-format-sd error reporting by
5841 * reporting the correct line-number when possible.
5842 */
5843 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5844 Warning("parsing [%s:%d] : backend '%s' : 'log-format-sd' directive is ignored in backends.\n",
5845 file, linenum, curproxy->id);
5846 err_code |= ERR_WARN;
5847 }
5848 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01005849 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
5850 if (*(args[1]) == 0) {
5851 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
5852 err_code |= ERR_ALERT | ERR_FATAL;
5853 goto out;
5854 }
5855 free(curproxy->log_tag);
5856 curproxy->log_tag = strdup(args[1]);
5857 }
William Lallemand0f99e342011-10-12 17:50:54 +02005858 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
5859 /* delete previous herited or defined syslog servers */
5860 struct logsrv *back;
5861
5862 if (*(args[1]) != 0) {
5863 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
5864 err_code |= ERR_ALERT | ERR_FATAL;
5865 goto out;
5866 }
5867
William Lallemand723b73a2012-02-08 16:37:49 +01005868 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
5869 LIST_DEL(&tmplogsrv->list);
5870 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02005871 }
5872 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005873 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02005874 struct logsrv *logsrv;
5875
Willy Tarreaubaaee002006-06-26 02:48:02 +02005876 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005877 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01005878 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02005879 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01005880 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02005881 LIST_INIT(&node->list);
5882 LIST_ADDQ(&curproxy->logsrvs, &node->list);
5883 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005884 }
5885 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005886 struct sockaddr_storage *sk;
5887 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02005888 int arg = 0;
5889 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02005890
5891 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005892
Willy Tarreau18324f52014-06-27 18:10:07 +02005893 /* just after the address, a length may be specified */
5894 if (strcmp(args[arg+2], "len") == 0) {
5895 len = atoi(args[arg+3]);
5896 if (len < 80 || len > 65535) {
5897 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
5898 file, linenum, args[arg+3]);
5899 err_code |= ERR_ALERT | ERR_FATAL;
5900 goto out;
5901 }
5902 logsrv->maxlen = len;
5903
5904 /* skip these two args */
5905 arg += 2;
5906 }
5907 else
5908 logsrv->maxlen = MAX_SYSLOG_LEN;
5909
5910 if (logsrv->maxlen > global.max_syslog_len) {
5911 global.max_syslog_len = logsrv->maxlen;
Dragan Dosen59cee972015-09-19 22:09:02 +02005912 logheader = realloc(logheader, global.max_syslog_len + 1);
Dragan Dosen1322d092015-09-22 16:05:32 +02005913 logheader_rfc5424 = realloc(logheader_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02005914 logline = realloc(logline, global.max_syslog_len + 1);
Dragan Dosen0b85ece2015-09-25 19:17:44 +02005915 logline_rfc5424 = realloc(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02005916 }
5917
Dragan Dosen1322d092015-09-22 16:05:32 +02005918 /* after the length, a format may be specified */
5919 if (strcmp(args[arg+2], "format") == 0) {
5920 logsrv->format = get_log_format(args[arg+3]);
5921 if (logsrv->format < 0) {
5922 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
5923 err_code |= ERR_ALERT | ERR_FATAL;
5924 goto out;
5925 }
5926
5927 /* skip these two args */
5928 arg += 2;
5929 }
5930
William Lallemanddf1425a2015-04-28 20:17:49 +02005931 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
5932 goto out;
5933
Willy Tarreau18324f52014-06-27 18:10:07 +02005934 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005935 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005936 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005937 err_code |= ERR_ALERT | ERR_FATAL;
5938 goto out;
5939
Willy Tarreaubaaee002006-06-26 02:48:02 +02005940 }
5941
William Lallemand0f99e342011-10-12 17:50:54 +02005942 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02005943 if (*(args[arg+3])) {
5944 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005945 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005946 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005947 err_code |= ERR_ALERT | ERR_FATAL;
5948 goto out;
5949
Willy Tarreaubaaee002006-06-26 02:48:02 +02005950 }
5951 }
5952
William Lallemand0f99e342011-10-12 17:50:54 +02005953 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02005954 if (*(args[arg+4])) {
5955 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01005956 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005957 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02005958 err_code |= ERR_ALERT | ERR_FATAL;
5959 goto out;
5960
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005961 }
5962 }
5963
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02005964 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005965 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005966 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005967 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005968 goto out;
5969 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005970
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005971 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005972
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005973 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005974 if (port1 != port2) {
5975 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5976 file, linenum, args[0], args[1]);
5977 err_code |= ERR_ALERT | ERR_FATAL;
5978 goto out;
5979 }
5980
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005981 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02005982 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005983 }
William Lallemand0f99e342011-10-12 17:50:54 +02005984
5985 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005986 }
5987 else {
5988 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
5989 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005990 err_code |= ERR_ALERT | ERR_FATAL;
5991 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005992 }
5993 }
5994 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005995 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005996 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01005997 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005998 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005999
Willy Tarreau977b8e42006-12-29 14:19:17 +01006000 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006001 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006002
Willy Tarreaubaaee002006-06-26 02:48:02 +02006003 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006004 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
6005 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02006006 err_code |= ERR_ALERT | ERR_FATAL;
6007 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006008 }
Willy Tarreau368480c2009-03-01 08:27:21 +01006009
6010 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01006011 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6012 free(curproxy->conn_src.iface_name);
6013 curproxy->conn_src.iface_name = NULL;
6014 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01006015
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006016 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006017 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006018 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006019 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006020 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006021 goto out;
6022 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006023
6024 proto = protocol_by_family(sk->ss_family);
6025 if (!proto || !proto->connect) {
6026 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006027 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006028 err_code |= ERR_ALERT | ERR_FATAL;
6029 goto out;
6030 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006031
6032 if (port1 != port2) {
6033 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6034 file, linenum, args[0], args[1]);
6035 err_code |= ERR_ALERT | ERR_FATAL;
6036 goto out;
6037 }
6038
Willy Tarreauef9a3602012-12-08 22:29:20 +01006039 curproxy->conn_src.source_addr = *sk;
6040 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006041
6042 cur_arg = 2;
6043 while (*(args[cur_arg])) {
6044 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau29fbe512015-08-20 19:35:14 +02006045#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006046 if (!*args[cur_arg + 1]) {
6047 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
6048 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006049 err_code |= ERR_ALERT | ERR_FATAL;
6050 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006051 }
6052
6053 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006054 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6055 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006056 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006057 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6058 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02006059 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
6060 char *name, *end;
6061
6062 name = args[cur_arg+1] + 7;
6063 while (isspace(*name))
6064 name++;
6065
6066 end = name;
6067 while (*end && !isspace(*end) && *end != ',' && *end != ')')
6068 end++;
6069
Willy Tarreauef9a3602012-12-08 22:29:20 +01006070 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6071 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
6072 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
6073 curproxy->conn_src.bind_hdr_len = end - name;
6074 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
6075 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
6076 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02006077
6078 /* now look for an occurrence number */
6079 while (isspace(*end))
6080 end++;
6081 if (*end == ',') {
6082 end++;
6083 name = end;
6084 if (*end == '-')
6085 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01006086 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02006087 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01006088 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006089 }
6090
Willy Tarreauef9a3602012-12-08 22:29:20 +01006091 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02006092 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
6093 " occurrences values smaller than %d.\n",
6094 file, linenum, MAX_HDR_HISTORY);
6095 err_code |= ERR_ALERT | ERR_FATAL;
6096 goto out;
6097 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006098 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01006099 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006100
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006101 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006102 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006103 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006104 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006105 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006106 goto out;
6107 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006108
6109 proto = protocol_by_family(sk->ss_family);
6110 if (!proto || !proto->connect) {
6111 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
6112 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006113 err_code |= ERR_ALERT | ERR_FATAL;
6114 goto out;
6115 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006116
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006117 if (port1 != port2) {
6118 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6119 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006120 err_code |= ERR_ALERT | ERR_FATAL;
6121 goto out;
6122 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006123 curproxy->conn_src.tproxy_addr = *sk;
6124 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006125 }
6126 global.last_checks |= LSTCHK_NETADM;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006127#else /* no TPROXY support */
6128 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01006129 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006130 err_code |= ERR_ALERT | ERR_FATAL;
6131 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006132#endif
6133 cur_arg += 2;
6134 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01006135 }
6136
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006137 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
6138#ifdef SO_BINDTODEVICE
6139 if (!*args[cur_arg + 1]) {
6140 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
6141 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006142 err_code |= ERR_ALERT | ERR_FATAL;
6143 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006144 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006145 free(curproxy->conn_src.iface_name);
6146 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
6147 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006148 global.last_checks |= LSTCHK_NETADM;
6149#else
6150 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
6151 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02006152 err_code |= ERR_ALERT | ERR_FATAL;
6153 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01006154#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006155 cur_arg += 2;
6156 continue;
6157 }
6158 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02006159 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006160 err_code |= ERR_ALERT | ERR_FATAL;
6161 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006162 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006163 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006164 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
6165 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
6166 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02006167 err_code |= ERR_ALERT | ERR_FATAL;
6168 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006169 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006170 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006171 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006172 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6173 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006174 err_code |= ERR_ALERT | ERR_FATAL;
6175 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006176 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006177
6178 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006179 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006180 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006181 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006182 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006183 }
6184 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006185 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006186 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006187 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006188 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006189 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006190 }
6191 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006192 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006193 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006194 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006195 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006196 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006197 }
6198 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006199 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006200 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006201 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006202 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006203 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006204 }
6205 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006206 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006207 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006208 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006209 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006210 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006211 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006212 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006213 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006214 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006215 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006216 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006217 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006218 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006219 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006220 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006221 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6222 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006223 err_code |= ERR_ALERT | ERR_FATAL;
6224 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006225 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006226
6227 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006228 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006229 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006230 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006231 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006232 }
6233 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006234 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006235 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006236 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006237 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006238 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006239 }
6240 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006241 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006242 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006243 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006244 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006245 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006246 }
6247 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006248 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006249 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006250 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006251 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006252 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006253 }
6254 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006255 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006256 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006257 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006258 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006259 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006260 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006261 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006262 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006263 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006264 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006265 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006266 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006267 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006268 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006269 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006270
Willy Tarreaubaaee002006-06-26 02:48:02 +02006271 if (curproxy == &defproxy) {
6272 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006273 err_code |= ERR_ALERT | ERR_FATAL;
6274 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006275 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006276 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006277 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006278
Willy Tarreaubaaee002006-06-26 02:48:02 +02006279 if (*(args[1]) == 0) {
6280 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006281 err_code |= ERR_ALERT | ERR_FATAL;
6282 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006283 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006284
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006285 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006286 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6287 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6288 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006289 err_code |= ERR_ALERT | ERR_FATAL;
6290 goto out;
6291 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006292 err_code |= warnif_cond_conflicts(cond,
6293 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6294 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006295 }
6296 else if (*args[2]) {
6297 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6298 file, linenum, args[0], args[2]);
6299 err_code |= ERR_ALERT | ERR_FATAL;
6300 goto out;
6301 }
6302
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006303 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006304 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006305 wl->s = strdup(args[1]);
6306 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02006307 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006308 }
6309 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006310 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006311 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6312 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006313 err_code |= ERR_ALERT | ERR_FATAL;
6314 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006315 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006316
Willy Tarreauade5ec42010-01-28 19:33:49 +01006317 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006318 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006319 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006320 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006321 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006322 }
6323 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006324 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006325 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006326 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006327 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006328 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006329 }
6330 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006331 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006332 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006333 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006334 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006335 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006336 }
6337 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006338 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006339 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6340 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006341 err_code |= ERR_ALERT | ERR_FATAL;
6342 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006343 }
6344
Willy Tarreauade5ec42010-01-28 19:33:49 +01006345 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006346 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006347 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006348 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006349 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006350 }
6351 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006352 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006353 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006354 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006355 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006356 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006357 }
6358 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006359 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006360 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006361 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006362 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006363 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006364 }
6365 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006366 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006367
Willy Tarreaubaaee002006-06-26 02:48:02 +02006368 if (curproxy == &defproxy) {
6369 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006370 err_code |= ERR_ALERT | ERR_FATAL;
6371 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006372 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006373 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006374 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006375
Willy Tarreaubaaee002006-06-26 02:48:02 +02006376 if (*(args[1]) == 0) {
6377 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006378 err_code |= ERR_ALERT | ERR_FATAL;
6379 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006380 }
6381
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006382 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006383 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6384 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6385 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006386 err_code |= ERR_ALERT | ERR_FATAL;
6387 goto out;
6388 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006389 err_code |= warnif_cond_conflicts(cond,
6390 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
6391 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006392 }
6393 else if (*args[2]) {
6394 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6395 file, linenum, args[0], args[2]);
6396 err_code |= ERR_ALERT | ERR_FATAL;
6397 goto out;
6398 }
6399
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006400 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006401 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006402 wl->s = strdup(args[1]);
6403 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006404 }
6405 else if (!strcmp(args[0], "errorloc") ||
6406 !strcmp(args[0], "errorloc302") ||
6407 !strcmp(args[0], "errorloc303")) { /* error location */
6408 int errnum, errlen;
6409 char *err;
6410
Willy Tarreau977b8e42006-12-29 14:19:17 +01006411 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006412 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006413
Willy Tarreaubaaee002006-06-26 02:48:02 +02006414 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006415 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006416 err_code |= ERR_ALERT | ERR_FATAL;
6417 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006418 }
6419
6420 errnum = atol(args[1]);
6421 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006422 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
6423 err = malloc(errlen);
6424 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006425 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006426 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
6427 err = malloc(errlen);
6428 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006429 }
6430
Willy Tarreau0f772532006-12-23 20:51:41 +01006431 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6432 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006433 chunk_destroy(&curproxy->errmsg[rc]);
6434 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01006435 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006436 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006437 }
Willy Tarreau0f772532006-12-23 20:51:41 +01006438
6439 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006440 Warning("parsing [%s:%d] : status code %d not handled by '%s', error relocation will be ignored.\n",
6441 file, linenum, errnum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006442 free(err);
6443 }
6444 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02006445 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
6446 int errnum, errlen, fd;
6447 char *err;
6448 struct stat stat;
6449
6450 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006451 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006452
6453 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006454 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006455 err_code |= ERR_ALERT | ERR_FATAL;
6456 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006457 }
6458
6459 fd = open(args[2], O_RDONLY);
6460 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
6461 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
6462 file, linenum, args[2], args[1]);
6463 if (fd >= 0)
6464 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02006465 err_code |= ERR_ALERT | ERR_FATAL;
6466 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006467 }
6468
Willy Tarreau27a674e2009-08-17 07:23:33 +02006469 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02006470 errlen = stat.st_size;
6471 } else {
6472 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02006473 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02006474 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02006475 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006476 }
6477
6478 err = malloc(errlen); /* malloc() must succeed during parsing */
6479 errnum = read(fd, err, errlen);
6480 if (errnum != errlen) {
6481 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
6482 file, linenum, args[2], args[1]);
6483 close(fd);
6484 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02006485 err_code |= ERR_ALERT | ERR_FATAL;
6486 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006487 }
6488 close(fd);
6489
6490 errnum = atol(args[1]);
6491 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6492 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006493 chunk_destroy(&curproxy->errmsg[rc]);
6494 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02006495 break;
6496 }
6497 }
6498
6499 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006500 Warning("parsing [%s:%d] : status code %d not handled by '%s', error customization will be ignored.\n",
6501 file, linenum, errnum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006502 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006503 free(err);
6504 }
6505 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006506 else if (!strcmp(args[0], "compression")) {
6507 struct comp *comp;
6508 if (curproxy->comp == NULL) {
6509 comp = calloc(1, sizeof(struct comp));
6510 curproxy->comp = comp;
6511 } else {
6512 comp = curproxy->comp;
6513 }
6514
6515 if (!strcmp(args[1], "algo")) {
6516 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01006517 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01006518
William Lallemand82fe75c2012-10-23 10:25:10 +02006519 cur_arg = 2;
6520 if (!*args[cur_arg]) {
6521 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
6522 file, linenum, args[0]);
6523 err_code |= ERR_ALERT | ERR_FATAL;
6524 goto out;
6525 }
6526 while (*(args[cur_arg])) {
6527 if (comp_append_algo(comp, args[cur_arg]) < 0) {
6528 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
6529 file, linenum, args[0], args[cur_arg]);
6530 err_code |= ERR_ALERT | ERR_FATAL;
6531 goto out;
6532 }
William Lallemand552df672012-11-07 13:21:47 +01006533 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
6534 curproxy->comp->algos->end(&ctx);
6535 } else {
6536 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
6537 file, linenum, args[0], args[cur_arg]);
6538 err_code |= ERR_ALERT | ERR_FATAL;
6539 goto out;
6540 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006541 cur_arg ++;
6542 continue;
6543 }
6544 }
Willy Tarreau70737d12012-10-27 00:34:28 +02006545 else if (!strcmp(args[1], "offload")) {
6546 comp->offload = 1;
6547 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006548 else if (!strcmp(args[1], "type")) {
6549 int cur_arg;
6550 cur_arg = 2;
6551 if (!*args[cur_arg]) {
6552 Alert("parsing [%s:%d] : '%s' expects <type>\n",
6553 file, linenum, args[0]);
6554 err_code |= ERR_ALERT | ERR_FATAL;
6555 goto out;
6556 }
6557 while (*(args[cur_arg])) {
6558 comp_append_type(comp, args[cur_arg]);
6559 cur_arg ++;
6560 continue;
6561 }
6562 }
6563 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02006564 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02006565 file, linenum, args[0]);
6566 err_code |= ERR_ALERT | ERR_FATAL;
6567 goto out;
6568 }
6569 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006570 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006571 struct cfg_kw_list *kwl;
6572 int index;
6573
6574 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6575 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6576 if (kwl->kw[index].section != CFG_LISTEN)
6577 continue;
6578 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6579 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006580 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006581 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006582 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006583 err_code |= ERR_ALERT | ERR_FATAL;
6584 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006585 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006586 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006587 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006588 err_code |= ERR_WARN;
6589 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006590 }
Willy Tarreau93893792009-07-23 13:19:11 +02006591 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006592 }
6593 }
6594 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006595
Willy Tarreau6daf3432008-01-22 16:44:08 +01006596 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006597 err_code |= ERR_ALERT | ERR_FATAL;
6598 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006599 }
Willy Tarreau93893792009-07-23 13:19:11 +02006600 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006601 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006602 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006603}
6604
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006605int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006606cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
6607{
6608#ifdef CONFIG_HAP_NS
6609 const char *err;
6610 const char *item = args[0];
6611
6612 if (!strcmp(item, "namespace_list")) {
6613 return 0;
6614 }
6615 else if (!strcmp(item, "namespace")) {
6616 size_t idx = 1;
6617 const char *current;
6618 while (*(current = args[idx++])) {
6619 err = invalid_char(current);
6620 if (err) {
6621 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6622 file, linenum, *err, item, current);
6623 return ERR_ALERT | ERR_FATAL;
6624 }
6625
6626 if (netns_store_lookup(current, strlen(current))) {
6627 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
6628 file, linenum, current);
6629 return ERR_ALERT | ERR_FATAL;
6630 }
6631 if (!netns_store_insert(current)) {
6632 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
6633 file, linenum, current);
6634 return ERR_ALERT | ERR_FATAL;
6635 }
6636 }
6637 }
6638
6639 return 0;
6640#else
6641 Alert("parsing [%s:%d]: namespace support is not compiled in.",
6642 file, linenum);
6643 return ERR_ALERT | ERR_FATAL;
6644#endif
6645}
6646
6647int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006648cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6649{
6650
6651 int err_code = 0;
6652 const char *err;
6653
6654 if (!strcmp(args[0], "userlist")) { /* new userlist */
6655 struct userlist *newul;
6656
6657 if (!*args[1]) {
6658 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6659 file, linenum, args[0]);
6660 err_code |= ERR_ALERT | ERR_FATAL;
6661 goto out;
6662 }
William Lallemand6e62fb62015-04-28 16:55:23 +02006663 if (alertif_too_many_args(1, file, linenum, args, &err_code))
6664 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006665
6666 err = invalid_char(args[1]);
6667 if (err) {
6668 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6669 file, linenum, *err, args[0], args[1]);
6670 err_code |= ERR_ALERT | ERR_FATAL;
6671 goto out;
6672 }
6673
6674 for (newul = userlist; newul; newul = newul->next)
6675 if (!strcmp(newul->name, args[1])) {
6676 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6677 file, linenum, args[1]);
6678 err_code |= ERR_WARN;
6679 goto out;
6680 }
6681
6682 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
6683 if (!newul) {
6684 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6685 err_code |= ERR_ALERT | ERR_ABORT;
6686 goto out;
6687 }
6688
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006689 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006690 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006691 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6692 err_code |= ERR_ALERT | ERR_ABORT;
6693 goto out;
6694 }
6695
6696 newul->next = userlist;
6697 userlist = newul;
6698
6699 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006700 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006701 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006702 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006703
6704 if (!*args[1]) {
6705 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6706 file, linenum, args[0]);
6707 err_code |= ERR_ALERT | ERR_FATAL;
6708 goto out;
6709 }
6710
6711 err = invalid_char(args[1]);
6712 if (err) {
6713 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6714 file, linenum, *err, args[0], args[1]);
6715 err_code |= ERR_ALERT | ERR_FATAL;
6716 goto out;
6717 }
6718
William Lallemand4ac9f542015-05-28 18:03:51 +02006719 if (!userlist)
6720 goto out;
6721
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006722 for (ag = userlist->groups; ag; ag = ag->next)
6723 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006724 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6725 file, linenum, args[1], userlist->name);
6726 err_code |= ERR_ALERT;
6727 goto out;
6728 }
6729
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006730 ag = calloc(1, sizeof(*ag));
6731 if (!ag) {
6732 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6733 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006734 goto out;
6735 }
6736
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006737 ag->name = strdup(args[1]);
6738 if (!ag) {
6739 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6740 err_code |= ERR_ALERT | ERR_ABORT;
6741 goto out;
6742 }
6743
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006744 cur_arg = 2;
6745
6746 while (*args[cur_arg]) {
6747 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006748 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006749 cur_arg += 2;
6750 continue;
6751 } else {
6752 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6753 file, linenum, args[0]);
6754 err_code |= ERR_ALERT | ERR_FATAL;
6755 goto out;
6756 }
6757 }
6758
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006759 ag->next = userlist->groups;
6760 userlist->groups = ag;
6761
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006762 } else if (!strcmp(args[0], "user")) { /* new user */
6763 struct auth_users *newuser;
6764 int cur_arg;
6765
6766 if (!*args[1]) {
6767 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6768 file, linenum, args[0]);
6769 err_code |= ERR_ALERT | ERR_FATAL;
6770 goto out;
6771 }
William Lallemand4ac9f542015-05-28 18:03:51 +02006772 if (!userlist)
6773 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006774
6775 for (newuser = userlist->users; newuser; newuser = newuser->next)
6776 if (!strcmp(newuser->user, args[1])) {
6777 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6778 file, linenum, args[1], userlist->name);
6779 err_code |= ERR_ALERT;
6780 goto out;
6781 }
6782
6783 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
6784 if (!newuser) {
6785 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6786 err_code |= ERR_ALERT | ERR_ABORT;
6787 goto out;
6788 }
6789
6790 newuser->user = strdup(args[1]);
6791
6792 newuser->next = userlist->users;
6793 userlist->users = newuser;
6794
6795 cur_arg = 2;
6796
6797 while (*args[cur_arg]) {
6798 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006799#ifdef CONFIG_HAP_CRYPT
6800 if (!crypt("", args[cur_arg + 1])) {
6801 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6802 file, linenum, newuser->user);
6803 err_code |= ERR_ALERT | ERR_FATAL;
6804 goto out;
6805 }
6806#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006807 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6808 file, linenum);
6809 err_code |= ERR_ALERT;
6810#endif
6811 newuser->pass = strdup(args[cur_arg + 1]);
6812 cur_arg += 2;
6813 continue;
6814 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6815 newuser->pass = strdup(args[cur_arg + 1]);
6816 newuser->flags |= AU_O_INSECURE;
6817 cur_arg += 2;
6818 continue;
6819 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006820 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006821 cur_arg += 2;
6822 continue;
6823 } else {
6824 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6825 file, linenum, args[0]);
6826 err_code |= ERR_ALERT | ERR_FATAL;
6827 goto out;
6828 }
6829 }
6830 } else {
6831 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6832 err_code |= ERR_ALERT | ERR_FATAL;
6833 }
6834
6835out:
6836 return err_code;
6837}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006838
6839/*
6840 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006841 * Returns the error code, 0 if OK, or any combination of :
6842 * - ERR_ABORT: must abort ASAP
6843 * - ERR_FATAL: we can continue parsing but not start the service
6844 * - ERR_WARN: a warning has been emitted
6845 * - ERR_ALERT: an alert has been emitted
6846 * Only the two first ones can stop processing, the two others are just
6847 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006848 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006849int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006850{
William Lallemand64e84512015-05-12 14:25:37 +02006851 char *thisline;
6852 int linesize = LINESIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006853 FILE *f;
6854 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02006855 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006856 struct cfg_section *cs = NULL;
6857 struct cfg_section *ics;
William Lallemand64e84512015-05-12 14:25:37 +02006858 int readbytes = 0;
6859
6860 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
William Lallemandb2f07452015-05-12 14:27:13 +02006861 Alert("parsing [%s] : out of memory.\n", file);
William Lallemand64e84512015-05-12 14:25:37 +02006862 return -1;
6863 }
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006864
6865 /* Register internal sections */
6866 if (!cfg_register_section("listen", cfg_parse_listen) ||
6867 !cfg_register_section("frontend", cfg_parse_listen) ||
6868 !cfg_register_section("backend", cfg_parse_listen) ||
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006869 !cfg_register_section("defaults", cfg_parse_listen) ||
6870 !cfg_register_section("global", cfg_parse_global) ||
6871 !cfg_register_section("userlist", cfg_parse_users) ||
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006872 !cfg_register_section("peers", cfg_parse_peers) ||
Simon Horman0d16a402015-01-30 11:22:58 +09006873 !cfg_register_section("mailers", cfg_parse_mailers) ||
Baptiste Assmann325137d2015-04-13 23:40:55 +02006874 !cfg_register_section("namespace_list", cfg_parse_netns) ||
6875 !cfg_register_section("resolvers", cfg_parse_resolvers))
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006876 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006877
Willy Tarreaubaaee002006-06-26 02:48:02 +02006878 if ((f=fopen(file,"r")) == NULL)
6879 return -1;
6880
William Lallemandb2f07452015-05-12 14:27:13 +02006881next_line:
William Lallemand64e84512015-05-12 14:25:37 +02006882 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02006883 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006884 char *end;
6885 char *args[MAX_LINE_ARGS + 1];
6886 char *line = thisline;
William Lallemandf9873ba2015-05-05 17:37:14 +02006887 int dquote = 0; /* double quote */
6888 int squote = 0; /* simple quote */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006889
Willy Tarreaubaaee002006-06-26 02:48:02 +02006890 linenum++;
6891
6892 end = line + strlen(line);
6893
William Lallemand64e84512015-05-12 14:25:37 +02006894 if (end-line == linesize-1 && *(end-1) != '\n') {
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006895 /* Check if we reached the limit and the last char is not \n.
6896 * Watch out for the last line without the terminating '\n'!
6897 */
William Lallemand64e84512015-05-12 14:25:37 +02006898 char *newline;
6899 int newlinesize = linesize * 2;
6900
6901 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
6902 if (newline == NULL) {
6903 Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
6904 file, linenum);
6905 err_code |= ERR_ALERT | ERR_FATAL;
6906 continue;
6907 }
6908
6909 readbytes = linesize - 1;
6910 linesize = newlinesize;
6911 thisline = newline;
6912 continue;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006913 }
6914
William Lallemand64e84512015-05-12 14:25:37 +02006915 readbytes = 0;
6916
Willy Tarreaubaaee002006-06-26 02:48:02 +02006917 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006918 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006919 line++;
William Lallemandf9873ba2015-05-05 17:37:14 +02006920
Willy Tarreaubaaee002006-06-26 02:48:02 +02006921 arg = 0;
6922 args[arg] = line;
6923
6924 while (*line && arg < MAX_LINE_ARGS) {
William Lallemandf9873ba2015-05-05 17:37:14 +02006925 if (*line == '"' && !squote) { /* double quote outside single quotes */
6926 if (dquote)
6927 dquote = 0;
6928 else
6929 dquote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02006930 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02006931 end--;
6932 }
6933 else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
6934 if (squote)
6935 squote = 0;
6936 else
6937 squote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02006938 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02006939 end--;
6940 }
6941 else if (*line == '\\' && !squote) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006942 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
6943 * C equivalent value. Other combinations left unchanged (eg: \1).
6944 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006945 int skip = 0;
6946 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
6947 *line = line[1];
6948 skip = 1;
6949 }
6950 else if (line[1] == 'r') {
6951 *line = '\r';
6952 skip = 1;
William Lallemandf9873ba2015-05-05 17:37:14 +02006953 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006954 else if (line[1] == 'n') {
6955 *line = '\n';
6956 skip = 1;
6957 }
6958 else if (line[1] == 't') {
6959 *line = '\t';
6960 skip = 1;
6961 }
6962 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01006963 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006964 unsigned char hex1, hex2;
6965 hex1 = toupper(line[2]) - '0';
6966 hex2 = toupper(line[3]) - '0';
6967 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
6968 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
6969 *line = (hex1<<4) + hex2;
6970 skip = 3;
6971 }
6972 else {
6973 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006974 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006975 }
William Lallemandf9873ba2015-05-05 17:37:14 +02006976 } else if (line[1] == '"') {
6977 *line = '"';
6978 skip = 1;
6979 } else if (line[1] == '\'') {
6980 *line = '\'';
6981 skip = 1;
William Lallemandb2f07452015-05-12 14:27:13 +02006982 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
6983 *line = '$';
6984 skip = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006985 }
6986 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01006987 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006988 end -= skip;
6989 }
6990 line++;
6991 }
William Lallemandf9873ba2015-05-05 17:37:14 +02006992 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006993 /* end of string, end of loop */
6994 *line = 0;
6995 break;
6996 }
William Lallemandf9873ba2015-05-05 17:37:14 +02006997 else if (!squote && !dquote && isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006998 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006999 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007000 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007001 line++;
7002 args[++arg] = line;
7003 }
William Lallemandb2f07452015-05-12 14:27:13 +02007004 else if (dquote && *line == '$') {
7005 /* environment variables are evaluated inside double quotes */
7006 char *var_beg;
7007 char *var_end;
7008 char save_char;
7009 char *value;
7010 int val_len;
7011 int newlinesize;
7012 int braces = 0;
7013
7014 var_beg = line + 1;
7015 var_end = var_beg;
7016
7017 if (*var_beg == '{') {
7018 var_beg++;
7019 var_end++;
7020 braces = 1;
7021 }
7022
7023 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
7024 Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
7025 err_code |= ERR_ALERT | ERR_FATAL;
7026 goto next_line; /* skip current line */
7027 }
7028
7029 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
7030 var_end++;
7031
7032 save_char = *var_end;
7033 *var_end = '\0';
7034 value = getenv(var_beg);
7035 *var_end = save_char;
7036 val_len = value ? strlen(value) : 0;
7037
7038 if (braces) {
7039 if (*var_end == '}') {
7040 var_end++;
7041 braces = 0;
7042 } else {
7043 Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
7044 err_code |= ERR_ALERT | ERR_FATAL;
7045 goto next_line; /* skip current line */
7046 }
7047 }
7048
7049 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
7050
7051 /* if not enough space in thisline */
7052 if (newlinesize > linesize) {
7053 char *newline;
7054
7055 newline = realloc(thisline, newlinesize * sizeof(*thisline));
7056 if (newline == NULL) {
7057 Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
7058 err_code |= ERR_ALERT | ERR_FATAL;
7059 goto next_line; /* slip current line */
7060 }
7061 /* recompute pointers if realloc returns a new pointer */
7062 if (newline != thisline) {
7063 int i;
7064 int diff;
7065
7066 for (i = 0; i <= arg; i++) {
7067 diff = args[i] - thisline;
7068 args[i] = newline + diff;
7069 }
7070
7071 diff = var_end - thisline;
7072 var_end = newline + diff;
7073 diff = end - thisline;
7074 end = newline + diff;
7075 diff = line - thisline;
7076 line = newline + diff;
7077 thisline = newline;
7078 }
7079 linesize = newlinesize;
7080 }
7081
7082 /* insert value inside the line */
7083 memmove(line + val_len, var_end, end - var_end + 1);
7084 memcpy(line, value, val_len);
7085 end += val_len - (var_end - line);
7086 line += val_len;
7087 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007088 else {
7089 line++;
7090 }
7091 }
William Lallemandb2f07452015-05-12 14:27:13 +02007092
William Lallemandf9873ba2015-05-05 17:37:14 +02007093 if (dquote) {
7094 Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
7095 err_code |= ERR_ALERT | ERR_FATAL;
7096 }
7097
7098 if (squote) {
7099 Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
7100 err_code |= ERR_ALERT | ERR_FATAL;
7101 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007102
7103 /* empty line */
7104 if (!**args)
7105 continue;
7106
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007107 if (*line) {
7108 /* we had to stop due to too many args.
7109 * Let's terminate the string, print the offending part then cut the
7110 * last arg.
7111 */
7112 while (*line && *line != '#' && *line != '\n' && *line != '\r')
7113 line++;
7114 *line = '\0';
7115
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01007116 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01007117 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007118 err_code |= ERR_ALERT | ERR_FATAL;
7119 args[arg] = line;
7120 }
7121
Willy Tarreau540abe42007-05-02 20:50:16 +02007122 /* zero out remaining args and ensure that at least one entry
7123 * is zeroed out.
7124 */
7125 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007126 args[arg] = line;
7127 }
7128
Willy Tarreau3842f002009-06-14 11:39:52 +02007129 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007130 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02007131 char *tmp;
7132
Willy Tarreau3842f002009-06-14 11:39:52 +02007133 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02007134 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007135 for (arg=0; *args[arg+1]; arg++)
7136 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02007137 *tmp = '\0'; // fix the next arg to \0
7138 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007139 }
Willy Tarreau3842f002009-06-14 11:39:52 +02007140 else if (!strcmp(args[0], "default")) {
7141 kwm = KWM_DEF;
7142 for (arg=0; *args[arg+1]; arg++)
7143 args[arg] = args[arg+1]; // shift args after inversion
7144 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007145
William Lallemand0f99e342011-10-12 17:50:54 +02007146 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
7147 strcmp(args[0], "log") != 0) {
7148 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02007149 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007150 }
7151
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007152 /* detect section start */
7153 list_for_each_entry(ics, &sections, list) {
7154 if (strcmp(args[0], ics->section_name) == 0) {
7155 cursection = ics->section_name;
7156 cs = ics;
7157 break;
7158 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007159 }
7160
Willy Tarreaubaaee002006-06-26 02:48:02 +02007161 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007162 if (cs)
7163 err_code |= cs->section_parser(file, linenum, args, kwm);
7164 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007165 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007166 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007167 }
Willy Tarreau058e9072009-07-20 09:30:05 +02007168
7169 if (err_code & ERR_ABORT)
7170 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007171 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01007172 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02007173 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007174 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02007175 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007176}
7177
Willy Tarreau64ab6072014-09-16 12:17:36 +02007178/* This function propagates processes from frontend <from> to backend <to> so
7179 * that it is always guaranteed that a backend pointed to by a frontend is
7180 * bound to all of its processes. After that, if the target is a "listen"
7181 * instance, the function recursively descends the target's own targets along
Willy Tarreau98d04852015-05-26 12:18:29 +02007182 * default_backend and use_backend rules. Since the bits are
Willy Tarreau64ab6072014-09-16 12:17:36 +02007183 * checked first to ensure that <to> is already bound to all processes of
7184 * <from>, there is no risk of looping and we ensure to follow the shortest
7185 * path to the destination.
7186 *
7187 * It is possible to set <to> to NULL for the first call so that the function
7188 * takes care of visiting the initial frontend in <from>.
7189 *
7190 * It is important to note that the function relies on the fact that all names
7191 * have already been resolved.
7192 */
7193void propagate_processes(struct proxy *from, struct proxy *to)
7194{
7195 struct switching_rule *rule;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007196
7197 if (to) {
7198 /* check whether we need to go down */
7199 if (from->bind_proc &&
7200 (from->bind_proc & to->bind_proc) == from->bind_proc)
7201 return;
7202
7203 if (!from->bind_proc && !to->bind_proc)
7204 return;
7205
7206 to->bind_proc = from->bind_proc ?
7207 (to->bind_proc | from->bind_proc) : 0;
7208
7209 /* now propagate down */
7210 from = to;
7211 }
7212
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01007213 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02007214 return;
7215
Willy Tarreauf6b70012014-12-18 14:00:43 +01007216 if (from->state == PR_STSTOPPED)
7217 return;
7218
Willy Tarreau64ab6072014-09-16 12:17:36 +02007219 /* default_backend */
7220 if (from->defbe.be)
7221 propagate_processes(from, from->defbe.be);
7222
7223 /* use_backend */
7224 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02007225 if (rule->dynamic)
7226 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007227 to = rule->be.backend;
7228 propagate_processes(from, to);
7229 }
Willy Tarreau64ab6072014-09-16 12:17:36 +02007230}
7231
Willy Tarreaubb925012009-07-23 13:36:36 +02007232/*
7233 * Returns the error code, 0 if OK, or any combination of :
7234 * - ERR_ABORT: must abort ASAP
7235 * - ERR_FATAL: we can continue parsing but not start the service
7236 * - ERR_WARN: a warning has been emitted
7237 * - ERR_ALERT: an alert has been emitted
7238 * Only the two first ones can stop processing, the two others are just
7239 * indicators.
7240 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007241int check_config_validity()
7242{
7243 int cfgerr = 0;
7244 struct proxy *curproxy = NULL;
7245 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02007246 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007247 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007248 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007249
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007250 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007251 /*
7252 * Now, check for the integrity of all that we have collected.
7253 */
7254
7255 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02007256 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007257
Willy Tarreau193b8c62012-11-22 00:17:38 +01007258 if (!global.tune.max_http_hdr)
7259 global.tune.max_http_hdr = MAX_HTTP_HDR;
7260
7261 if (!global.tune.cookie_len)
7262 global.tune.cookie_len = CAPTURE_LEN;
7263
7264 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
7265
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007266 /* Post initialisation of the users and groups lists. */
7267 err_code = userlist_postinit();
7268 if (err_code != ERR_NONE)
7269 goto out;
7270
Willy Tarreau55bc0f82009-03-15 14:51:53 +01007271 /* first, we will invert the proxy list order */
7272 curproxy = NULL;
7273 while (proxy) {
7274 struct proxy *next;
7275
7276 next = proxy->next;
7277 proxy->next = curproxy;
7278 curproxy = proxy;
7279 if (!next)
7280 break;
7281 proxy = next;
7282 }
7283
Willy Tarreau419ead82014-09-16 13:41:21 +02007284 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007285 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007286 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01007287 struct sticking_rule *mrule;
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007288 struct act_rule *trule;
7289 struct act_rule *hrqrule;
Dragan Dosen1322d092015-09-22 16:05:32 +02007290 struct logsrv *tmplogsrv;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007291 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01007292 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007293
Willy Tarreau050536d2012-10-04 08:47:34 +02007294 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007295 /* proxy ID not set, use automatic numbering with first
7296 * spare entry starting with next_pxid.
7297 */
7298 next_pxid = get_next_id(&used_proxy_id, next_pxid);
7299 curproxy->conf.id.key = curproxy->uuid = next_pxid;
7300 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007301 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007302 next_pxid++;
7303
Willy Tarreau55ea7572007-06-17 19:56:27 +02007304
Willy Tarreaubaaee002006-06-26 02:48:02 +02007305 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02007306 /* ensure we don't keep listeners uselessly bound */
7307 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02007308 free((void *)curproxy->table.peers.name);
7309 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007310 continue;
7311 }
7312
Willy Tarreau102df612014-05-07 23:56:38 +02007313 /* Check multi-process mode compatibility for the current proxy */
7314
7315 if (curproxy->bind_proc) {
7316 /* an explicit bind-process was specified, let's check how many
7317 * processes remain.
7318 */
David Carliere6c39412015-07-02 07:00:17 +00007319 nbproc = my_popcountl(curproxy->bind_proc);
Willy Tarreau102df612014-05-07 23:56:38 +02007320
7321 curproxy->bind_proc &= nbits(global.nbproc);
7322 if (!curproxy->bind_proc && nbproc == 1) {
7323 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);
7324 curproxy->bind_proc = 1;
7325 }
7326 else if (!curproxy->bind_proc && nbproc > 1) {
7327 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);
7328 curproxy->bind_proc = 0;
7329 }
7330 }
7331
Willy Tarreau3d209582014-05-09 17:06:11 +02007332 /* check and reduce the bind-proc of each listener */
7333 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7334 unsigned long mask;
7335
7336 if (!bind_conf->bind_proc)
7337 continue;
7338
7339 mask = nbits(global.nbproc);
7340 if (curproxy->bind_proc)
7341 mask &= curproxy->bind_proc;
7342 /* mask cannot be null here thanks to the previous checks */
7343
David Carliere6c39412015-07-02 07:00:17 +00007344 nbproc = my_popcountl(bind_conf->bind_proc);
Willy Tarreau3d209582014-05-09 17:06:11 +02007345 bind_conf->bind_proc &= mask;
7346
7347 if (!bind_conf->bind_proc && nbproc == 1) {
7348 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",
7349 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7350 bind_conf->bind_proc = mask & ~(mask - 1);
7351 }
7352 else if (!bind_conf->bind_proc && nbproc > 1) {
7353 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",
7354 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7355 bind_conf->bind_proc = 0;
7356 }
7357 }
7358
Willy Tarreauff01a212009-03-15 13:46:16 +01007359 switch (curproxy->mode) {
7360 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007361 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007362 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007363 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
7364 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007365 cfgerr++;
7366 }
7367
7368 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007369 Warning("config : servers will be ignored for %s '%s'.\n",
7370 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007371 break;
7372
7373 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007374 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007375 break;
7376
7377 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01007378 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01007379 break;
7380 }
7381
Willy Tarreauf3934b82015-08-11 11:36:45 +02007382 if ((curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->conf.listeners)) {
7383 Warning("config : %s '%s' has no 'bind' directive. Please declare it as a backend if this was intended.\n",
7384 proxy_type_str(curproxy), curproxy->id);
7385 err_code |= ERR_WARN;
7386 }
7387
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007388 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007389 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007390 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007391 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
7392 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007393 cfgerr++;
7394 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007395#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007396 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007397 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
7398 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007399 cfgerr++;
7400 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007401#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02007402 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007403 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
7404 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007405 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007406 }
7407 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02007408 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007409 /* If no LB algo is set in a backend, and we're not in
7410 * transparent mode, dispatch mode nor proxy mode, we
7411 * want to use balance roundrobin by default.
7412 */
7413 curproxy->lbprm.algo &= ~BE_LB_ALGO;
7414 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007415 }
7416 }
Willy Tarreau193cf932007-09-17 10:17:23 +02007417
Willy Tarreau1620ec32011-08-06 17:05:02 +02007418 if (curproxy->options & PR_O_DISPATCH)
7419 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
7420 else if (curproxy->options & PR_O_HTTP_PROXY)
7421 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
7422 else if (curproxy->options & PR_O_TRANSP)
7423 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01007424
Willy Tarreau1620ec32011-08-06 17:05:02 +02007425 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
7426 if (curproxy->options & PR_O_DISABLE404) {
7427 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7428 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
7429 err_code |= ERR_WARN;
7430 curproxy->options &= ~PR_O_DISABLE404;
7431 }
7432 if (curproxy->options2 & PR_O2_CHK_SNDST) {
7433 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7434 "send-state", proxy_type_str(curproxy), curproxy->id);
7435 err_code |= ERR_WARN;
7436 curproxy->options &= ~PR_O2_CHK_SNDST;
7437 }
Willy Tarreauef781042010-01-27 11:53:01 +01007438 }
7439
Simon Horman98637e52014-06-20 12:30:16 +09007440 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
7441 if (!global.external_check) {
7442 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
7443 curproxy->id, "option external-check");
7444 cfgerr++;
7445 }
7446 if (!curproxy->check_command) {
7447 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
7448 curproxy->id, "option external-check");
7449 cfgerr++;
7450 }
7451 }
7452
Simon Horman64e34162015-02-06 11:11:57 +09007453 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007454 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
7455 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Pieter Baauw8669e972015-08-17 00:45:05 +02007456 "'email-alert from', 'email-alert level' 'email-alert mailers', "
7457 "'email-alert myhostname', or 'email-alert to' "
7458 "requires each of 'email-alert from', 'email-alert mailers' and 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007459 "to be present).\n",
7460 proxy_type_str(curproxy), curproxy->id);
7461 err_code |= ERR_WARN;
7462 free_email_alert(curproxy);
7463 }
7464 if (!curproxy->email_alert.myhostname)
7465 curproxy->email_alert.myhostname = hostname;
Simon Horman9dc49962015-01-30 11:22:59 +09007466 }
7467
Simon Horman98637e52014-06-20 12:30:16 +09007468 if (curproxy->check_command) {
7469 int clear = 0;
7470 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7471 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7472 "external-check command", proxy_type_str(curproxy), curproxy->id);
7473 err_code |= ERR_WARN;
7474 clear = 1;
7475 }
7476 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
7477 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-command path' is not set.\n",
7478 curproxy->id, "external-check command");
7479 cfgerr++;
7480 }
7481 if (clear) {
7482 free(curproxy->check_command);
7483 curproxy->check_command = NULL;
7484 }
7485 }
7486
7487 if (curproxy->check_path) {
7488 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7489 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7490 "external-check path", proxy_type_str(curproxy), curproxy->id);
7491 err_code |= ERR_WARN;
7492 free(curproxy->check_path);
7493 curproxy->check_path = NULL;
7494 }
7495 }
7496
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007497 /* if a default backend was specified, let's find it */
7498 if (curproxy->defbe.name) {
7499 struct proxy *target;
7500
Willy Tarreauafb39922015-05-26 12:04:09 +02007501 target = proxy_be_by_name(curproxy->defbe.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007502 if (!target) {
7503 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
7504 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007505 cfgerr++;
7506 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007507 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
7508 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02007509 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007510 } else if (target->mode != curproxy->mode &&
7511 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7512
7513 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) as its default backend (see 'mode').\n",
7514 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7515 curproxy->conf.file, curproxy->conf.line,
7516 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7517 target->conf.file, target->conf.line);
7518 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007519 } else {
7520 free(curproxy->defbe.name);
7521 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01007522
7523 /* Emit a warning if this proxy also has some servers */
7524 if (curproxy->srv) {
7525 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
7526 curproxy->id);
7527 err_code |= ERR_WARN;
7528 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007529 }
7530 }
7531
Willy Tarreau55ea7572007-06-17 19:56:27 +02007532 /* find the target proxy for 'use_backend' rules */
7533 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007534 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007535 struct logformat_node *node;
7536 char *pxname;
7537
7538 /* Try to parse the string as a log format expression. If the result
7539 * of the parsing is only one entry containing a simple string, then
7540 * it's a standard string corresponding to a static rule, thus the
7541 * parsing is cancelled and be.name is restored to be resolved.
7542 */
7543 pxname = rule->be.name;
7544 LIST_INIT(&rule->be.expr);
7545 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
7546 curproxy->conf.args.file, curproxy->conf.args.line);
7547 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
7548
7549 if (!LIST_ISEMPTY(&rule->be.expr)) {
7550 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
7551 rule->dynamic = 1;
7552 free(pxname);
7553 continue;
7554 }
7555 /* simple string: free the expression and fall back to static rule */
7556 free(node->arg);
7557 free(node);
7558 }
7559
7560 rule->dynamic = 0;
7561 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007562
Willy Tarreauafb39922015-05-26 12:04:09 +02007563 target = proxy_be_by_name(rule->be.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007564 if (!target) {
7565 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
7566 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007567 cfgerr++;
7568 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007569 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
7570 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007571 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007572 } else if (target->mode != curproxy->mode &&
7573 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7574
7575 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) in a 'use_backend' rule (see 'mode').\n",
7576 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7577 curproxy->conf.file, curproxy->conf.line,
7578 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7579 target->conf.file, target->conf.line);
7580 cfgerr++;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007581 } else {
7582 free((void *)rule->be.name);
7583 rule->be.backend = target;
7584 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007585 }
7586
Willy Tarreau64ab6072014-09-16 12:17:36 +02007587 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007588 list_for_each_entry(srule, &curproxy->server_rules, list) {
7589 struct server *target = findserver(curproxy, srule->srv.name);
7590
7591 if (!target) {
7592 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7593 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7594 cfgerr++;
7595 continue;
7596 }
7597 free((void *)srule->srv.name);
7598 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007599 }
7600
Emeric Brunb982a3d2010-01-04 15:45:53 +01007601 /* find the target table for 'stick' rules */
7602 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7603 struct proxy *target;
7604
Emeric Brun1d33b292010-01-04 15:47:17 +01007605 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7606 if (mrule->flags & STK_IS_STORE)
7607 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7608
Emeric Brunb982a3d2010-01-04 15:45:53 +01007609 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007610 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007611 else
7612 target = curproxy;
7613
7614 if (!target) {
7615 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7616 curproxy->id, mrule->table.name);
7617 cfgerr++;
7618 }
7619 else if (target->table.size == 0) {
7620 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7621 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7622 cfgerr++;
7623 }
Willy Tarreau12785782012-04-27 21:37:17 +02007624 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7625 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007626 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7627 cfgerr++;
7628 }
7629 else {
7630 free((void *)mrule->table.name);
7631 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007632 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007633 }
7634 }
7635
7636 /* find the target table for 'store response' rules */
7637 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7638 struct proxy *target;
7639
Emeric Brun1d33b292010-01-04 15:47:17 +01007640 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7641
Emeric Brunb982a3d2010-01-04 15:45:53 +01007642 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007643 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007644 else
7645 target = curproxy;
7646
7647 if (!target) {
7648 Alert("Proxy '%s': unable to find store table '%s'.\n",
7649 curproxy->id, mrule->table.name);
7650 cfgerr++;
7651 }
7652 else if (target->table.size == 0) {
7653 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7654 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7655 cfgerr++;
7656 }
Willy Tarreau12785782012-04-27 21:37:17 +02007657 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7658 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007659 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7660 cfgerr++;
7661 }
7662 else {
7663 free((void *)mrule->table.name);
7664 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007665 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007666 }
7667 }
7668
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007669 /* find the target table for 'tcp-request' layer 4 rules */
7670 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
7671 struct proxy *target;
7672
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007673 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007674 continue;
7675
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007676 if (trule->arg.trk_ctr.table.n)
7677 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007678 else
7679 target = curproxy;
7680
7681 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007682 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007683 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007684 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007685 cfgerr++;
7686 }
7687 else if (target->table.size == 0) {
7688 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007689 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007690 cfgerr++;
7691 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007692 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007693 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007694 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007695 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007696 cfgerr++;
7697 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007698 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007699 free(trule->arg.trk_ctr.table.n);
7700 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007701 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007702 * to pass a list of counters to track and allocate them right here using
7703 * stktable_alloc_data_type().
7704 */
7705 }
7706 }
7707
Willy Tarreaud1f96522010-08-03 19:34:32 +02007708 /* find the target table for 'tcp-request' layer 6 rules */
7709 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7710 struct proxy *target;
7711
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007712 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02007713 continue;
7714
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007715 if (trule->arg.trk_ctr.table.n)
7716 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007717 else
7718 target = curproxy;
7719
7720 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007721 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007722 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007723 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02007724 cfgerr++;
7725 }
7726 else if (target->table.size == 0) {
7727 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007728 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007729 cfgerr++;
7730 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007731 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007732 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007733 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007734 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007735 cfgerr++;
7736 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02007737 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007738 free(trule->arg.trk_ctr.table.n);
7739 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007740 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02007741 * to pass a list of counters to track and allocate them right here using
7742 * stktable_alloc_data_type().
7743 */
7744 }
7745 }
7746
Willy Tarreau09448f72014-06-25 18:12:15 +02007747 /* find the target table for 'http-request' layer 7 rules */
7748 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7749 struct proxy *target;
7750
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007751 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau09448f72014-06-25 18:12:15 +02007752 continue;
7753
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007754 if (hrqrule->arg.trk_ctr.table.n)
7755 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
Willy Tarreau09448f72014-06-25 18:12:15 +02007756 else
7757 target = curproxy;
7758
7759 if (!target) {
7760 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007761 curproxy->id, hrqrule->arg.trk_ctr.table.n,
Willy Tarreau09448f72014-06-25 18:12:15 +02007762 http_req_trk_idx(hrqrule->action));
7763 cfgerr++;
7764 }
7765 else if (target->table.size == 0) {
7766 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007767 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau09448f72014-06-25 18:12:15 +02007768 cfgerr++;
7769 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007770 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau09448f72014-06-25 18:12:15 +02007771 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007772 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau09448f72014-06-25 18:12:15 +02007773 http_req_trk_idx(hrqrule->action));
7774 cfgerr++;
7775 }
7776 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007777 free(hrqrule->arg.trk_ctr.table.n);
7778 hrqrule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau09448f72014-06-25 18:12:15 +02007779 /* Note: if we decide to enhance the track-sc syntax, we may be able
7780 * to pass a list of counters to track and allocate them right here using
7781 * stktable_alloc_data_type().
7782 */
7783 }
7784 }
7785
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02007786 /* move any "block" rules at the beginning of the http-request rules */
7787 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
7788 /* insert block_rules into http_req_rules at the beginning */
7789 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
7790 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
7791 curproxy->block_rules.n->p = &curproxy->http_req_rules;
7792 curproxy->http_req_rules.n = curproxy->block_rules.n;
7793 LIST_INIT(&curproxy->block_rules);
7794 }
7795
Emeric Brun32da3c42010-09-23 18:39:19 +02007796 if (curproxy->table.peers.name) {
7797 struct peers *curpeers = peers;
7798
7799 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
7800 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
7801 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01007802 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02007803 break;
7804 }
7805 }
7806
7807 if (!curpeers) {
7808 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
7809 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007810 free((void *)curproxy->table.peers.name);
7811 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007812 cfgerr++;
7813 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02007814 else if (curpeers->state == PR_STSTOPPED) {
7815 /* silently disable this peers section */
7816 curproxy->table.peers.p = NULL;
7817 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007818 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02007819 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
7820 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007821 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007822 cfgerr++;
7823 }
7824 }
7825
Simon Horman9dc49962015-01-30 11:22:59 +09007826
7827 if (curproxy->email_alert.mailers.name) {
7828 struct mailers *curmailers = mailers;
7829
7830 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
7831 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
7832 free(curproxy->email_alert.mailers.name);
7833 curproxy->email_alert.mailers.m = curmailers;
7834 curmailers->users++;
7835 break;
7836 }
7837 }
7838
7839 if (!curmailers) {
7840 Alert("Proxy '%s': unable to find mailers '%s'.\n",
7841 curproxy->id, curproxy->email_alert.mailers.name);
7842 free_email_alert(curproxy);
7843 cfgerr++;
7844 }
7845 }
7846
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007847 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01007848 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007849 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
7850 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
7851 "proxy", curproxy->id);
7852 cfgerr++;
7853 goto out_uri_auth_compat;
7854 }
7855
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007856 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007857 const char *uri_auth_compat_req[10];
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007858 struct act_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01007859 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007860
Willy Tarreau95fa4692010-02-01 13:05:50 +01007861 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
7862 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007863
7864 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007865 uri_auth_compat_req[i++] = "realm";
7866 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
7867 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007868
Willy Tarreau95fa4692010-02-01 13:05:50 +01007869 uri_auth_compat_req[i++] = "unless";
7870 uri_auth_compat_req[i++] = "{";
7871 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
7872 uri_auth_compat_req[i++] = "}";
7873 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007874
Willy Tarreauff011f22011-01-06 17:51:27 +01007875 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
7876 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007877 cfgerr++;
7878 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007879 }
7880
Willy Tarreauff011f22011-01-06 17:51:27 +01007881 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01007882
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007883 if (curproxy->uri_auth->auth_realm) {
7884 free(curproxy->uri_auth->auth_realm);
7885 curproxy->uri_auth->auth_realm = NULL;
7886 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007887
7888 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007889 }
7890out_uri_auth_compat:
7891
Dragan Dosen68d2e3a2015-09-19 22:35:44 +02007892 /* write a syslog header string that contains hostname, log_tag and pid */
Dragan Dosen1322d092015-09-22 16:05:32 +02007893 list_for_each_entry(tmplogsrv, &curproxy->logsrvs, list) {
7894 char *hdr;
7895 struct chunk *htp;
Dragan Dosen1322d092015-09-22 16:05:32 +02007896 char *host = global.log_send_hostname;
Dragan Dosen68d2e3a2015-09-19 22:35:44 +02007897
Dragan Dosen1322d092015-09-22 16:05:32 +02007898 switch (tmplogsrv->format) {
7899 case LOG_FORMAT_RFC3164:
7900 hdr = logheader;
7901 htp = &curproxy->log_htp;
Dragan Dosen1322d092015-09-22 16:05:32 +02007902 host = host ? host : "";
7903 break;
Dragan Dosen68d2e3a2015-09-19 22:35:44 +02007904
Dragan Dosen1322d092015-09-22 16:05:32 +02007905 case LOG_FORMAT_RFC5424:
7906 hdr = logheader_rfc5424;
7907 htp = &curproxy->log_htp_rfc5424;
Dragan Dosenc8cfa7b2015-09-28 13:28:21 +02007908 host = host ? host : hostname;
Dragan Dosen1322d092015-09-22 16:05:32 +02007909 break;
7910
7911 default:
7912 continue; /* must never happen */
7913 }
7914
7915 if (htp->str)
7916 continue;
7917
Dragan Dosenc8cfa7b2015-09-28 13:28:21 +02007918 htp->str = lf_host_tag_pid(hdr, tmplogsrv->format, host,
Dragan Dosen1322d092015-09-22 16:05:32 +02007919 curproxy->log_tag ? curproxy->log_tag : global.log_tag,
7920 pid, global.max_syslog_len);
7921
Dragan Dosen1322d092015-09-22 16:05:32 +02007922 if ((htp->str == NULL) ||
7923 ((htp->len = htp->str - hdr) >= global.max_syslog_len)) {
7924 Alert("Proxy '%s': cannot write a syslog header string that contains "
7925 "hostname, log_tag and pid.\n",
7926 curproxy->id);
7927 cfgerr++;
7928 goto out_host_tag_pid;
7929 }
7930
7931 htp->str = (char *)malloc(htp->len);
7932 memcpy(htp->str, hdr, htp->len);
7933 htp->size = 0;
7934
7935 hdr[0] = 0;
7936 }
7937out_host_tag_pid:
Dragan Dosen68d2e3a2015-09-19 22:35:44 +02007938
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007939 /* compile the log format */
7940 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02007941 if (curproxy->conf.logformat_string != default_http_log_format &&
7942 curproxy->conf.logformat_string != default_tcp_log_format &&
7943 curproxy->conf.logformat_string != clf_http_log_format)
7944 free(curproxy->conf.logformat_string);
7945 curproxy->conf.logformat_string = NULL;
7946 free(curproxy->conf.lfs_file);
7947 curproxy->conf.lfs_file = NULL;
7948 curproxy->conf.lfs_line = 0;
Dragan Dosen0b85ece2015-09-25 19:17:44 +02007949
7950 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
7951 free(curproxy->conf.logformat_sd_string);
7952 curproxy->conf.logformat_sd_string = NULL;
7953 free(curproxy->conf.lfsd_file);
7954 curproxy->conf.lfsd_file = NULL;
7955 curproxy->conf.lfsd_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007956 }
7957
Willy Tarreau62a61232013-04-12 18:13:46 +02007958 if (curproxy->conf.logformat_string) {
7959 curproxy->conf.args.ctx = ARGC_LOG;
7960 curproxy->conf.args.file = curproxy->conf.lfs_file;
7961 curproxy->conf.args.line = curproxy->conf.lfs_line;
7962 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007963 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007964 curproxy->conf.args.file = NULL;
7965 curproxy->conf.args.line = 0;
7966 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007967
Dragan Dosen0b85ece2015-09-25 19:17:44 +02007968 if (curproxy->conf.logformat_sd_string) {
7969 curproxy->conf.args.ctx = ARGC_LOGSD;
7970 curproxy->conf.args.file = curproxy->conf.lfsd_file;
7971 curproxy->conf.args.line = curproxy->conf.lfsd_line;
7972 parse_logformat_string(curproxy->conf.logformat_sd_string, curproxy, &curproxy->logformat_sd, LOG_OPT_MANDATORY,
7973 SMP_VAL_FE_LOG_END, curproxy->conf.lfsd_file, curproxy->conf.lfsd_line);
7974 add_to_logformat_list(NULL, NULL, LF_SEPARATOR, &curproxy->logformat_sd);
7975 curproxy->conf.args.file = NULL;
7976 curproxy->conf.args.line = 0;
7977 }
7978
Willy Tarreau62a61232013-04-12 18:13:46 +02007979 if (curproxy->conf.uniqueid_format_string) {
7980 curproxy->conf.args.ctx = ARGC_UIF;
7981 curproxy->conf.args.file = curproxy->conf.uif_file;
7982 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01007983 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Godbachd9722032014-12-18 15:44:58 +08007984 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007985 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007986 curproxy->conf.args.file = NULL;
7987 curproxy->conf.args.line = 0;
7988 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007989
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007990 /* only now we can check if some args remain unresolved.
7991 * This must be done after the users and groups resolution.
7992 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007993 cfgerr += smp_resolve_args(curproxy);
7994 if (!cfgerr)
7995 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01007996
Willy Tarreau2738a142006-07-08 17:28:09 +02007997 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007998 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02007999 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02008000 (!curproxy->timeout.connect ||
8001 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008002 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02008003 " | While not properly invalid, you will certainly encounter various problems\n"
8004 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01008005 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008006 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008007 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02008008 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02008009
Willy Tarreau1fa31262007-12-03 00:36:16 +01008010 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
8011 * We must still support older configurations, so let's find out whether those
8012 * parameters have been set or must be copied from contimeouts.
8013 */
8014 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008015 if (!curproxy->timeout.tarpit ||
8016 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008017 /* tarpit timeout not set. We search in the following order:
8018 * default.tarpit, curr.connect, default.connect.
8019 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008020 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008021 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008022 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008023 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008024 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008025 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008026 }
8027 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008028 (!curproxy->timeout.queue ||
8029 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008030 /* queue timeout not set. We search in the following order:
8031 * default.queue, curr.connect, default.connect.
8032 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008033 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008034 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008035 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008036 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008037 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008038 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008039 }
8040 }
8041
Willy Tarreau1620ec32011-08-06 17:05:02 +02008042 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01008043 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
8044 curproxy->check_req = (char *)malloc(curproxy->check_len);
8045 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02008046 }
8047
Willy Tarreau215663d2014-06-13 18:30:23 +02008048 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
8049 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
8050 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
8051 proxy_type_str(curproxy), curproxy->id);
8052 err_code |= ERR_WARN;
8053 }
8054
Willy Tarreau193b8c62012-11-22 00:17:38 +01008055 /* ensure that cookie capture length is not too large */
8056 if (curproxy->capture_len >= global.tune.cookie_len) {
8057 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
8058 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
8059 err_code |= ERR_WARN;
8060 curproxy->capture_len = global.tune.cookie_len - 1;
8061 }
8062
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008063 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01008064 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008065 curproxy->req_cap_pool = create_pool("ptrcap",
8066 curproxy->nb_req_cap * sizeof(char *),
8067 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008068 }
8069
8070 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008071 curproxy->rsp_cap_pool = create_pool("ptrcap",
8072 curproxy->nb_rsp_cap * sizeof(char *),
8073 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008074 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008075
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02008076 switch (curproxy->load_server_state_from_file) {
8077 case PR_SRV_STATE_FILE_UNSPEC:
8078 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
8079 break;
8080 case PR_SRV_STATE_FILE_GLOBAL:
8081 if (!global.server_state_file) {
8082 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",
8083 curproxy->id);
8084 err_code |= ERR_WARN;
8085 }
8086 break;
8087 }
8088
Willy Tarreaubaaee002006-06-26 02:48:02 +02008089 /* first, we will invert the servers list order */
8090 newsrv = NULL;
8091 while (curproxy->srv) {
8092 struct server *next;
8093
8094 next = curproxy->srv->next;
8095 curproxy->srv->next = newsrv;
8096 newsrv = curproxy->srv;
8097 if (!next)
8098 break;
8099 curproxy->srv = next;
8100 }
8101
Willy Tarreau17edc812014-01-03 12:14:34 +01008102 /* Check that no server name conflicts. This causes trouble in the stats.
8103 * We only emit a warning for the first conflict affecting each server,
8104 * in order to avoid combinatory explosion if all servers have the same
8105 * name. We do that only for servers which do not have an explicit ID,
8106 * because these IDs were made also for distinguishing them and we don't
8107 * want to annoy people who correctly manage them.
8108 */
8109 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
8110 struct server *other_srv;
8111
8112 if (newsrv->puid)
8113 continue;
8114
8115 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
8116 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
8117 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
8118 newsrv->conf.file, newsrv->conf.line,
8119 proxy_type_str(curproxy), curproxy->id,
8120 newsrv->id, other_srv->conf.line);
8121 break;
8122 }
8123 }
8124 }
8125
Willy Tarreaudd701652010-05-25 23:03:02 +02008126 /* assign automatic UIDs to servers which don't have one yet */
8127 next_id = 1;
8128 newsrv = curproxy->srv;
8129 while (newsrv != NULL) {
8130 if (!newsrv->puid) {
8131 /* server ID not set, use automatic numbering with first
8132 * spare entry starting with next_svid.
8133 */
8134 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
8135 newsrv->conf.id.key = newsrv->puid = next_id;
8136 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
8137 }
8138 next_id++;
8139 newsrv = newsrv->next;
8140 }
8141
Willy Tarreau20697042007-11-15 23:26:18 +01008142 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01008143 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02008144
Willy Tarreau62c3be22012-01-20 13:12:32 +01008145 /*
8146 * If this server supports a maxconn parameter, it needs a dedicated
8147 * tasks to fill the emptied slots when a connection leaves.
8148 * Also, resolve deferred tracking dependency if needed.
8149 */
8150 newsrv = curproxy->srv;
8151 while (newsrv != NULL) {
8152 if (newsrv->minconn > newsrv->maxconn) {
8153 /* Only 'minconn' was specified, or it was higher than or equal
8154 * to 'maxconn'. Let's turn this into maxconn and clean it, as
8155 * this will avoid further useless expensive computations.
8156 */
8157 newsrv->maxconn = newsrv->minconn;
8158 } else if (newsrv->maxconn && !newsrv->minconn) {
8159 /* minconn was not specified, so we set it to maxconn */
8160 newsrv->minconn = newsrv->maxconn;
8161 }
8162
Emeric Brun01f8e2f2012-05-18 16:02:00 +02008163#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02008164 if (newsrv->use_ssl || newsrv->check.use_ssl)
8165 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02008166#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02008167
Willy Tarreau2f075e92013-12-03 11:11:34 +01008168 /* set the check type on the server */
8169 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
8170
Willy Tarreau62c3be22012-01-20 13:12:32 +01008171 if (newsrv->trackit) {
8172 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02008173 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008174 char *pname, *sname;
8175
8176 pname = newsrv->trackit;
8177 sname = strrchr(pname, '/');
8178
8179 if (sname)
8180 *sname++ = '\0';
8181 else {
8182 sname = pname;
8183 pname = NULL;
8184 }
8185
8186 if (pname) {
Willy Tarreau9e0bb102015-05-26 11:24:42 +02008187 px = proxy_be_by_name(pname);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008188 if (!px) {
8189 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
8190 proxy_type_str(curproxy), curproxy->id,
8191 newsrv->id, pname);
8192 cfgerr++;
8193 goto next_srv;
8194 }
8195 } else
8196 px = curproxy;
8197
8198 srv = findserver(px, sname);
8199 if (!srv) {
8200 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
8201 proxy_type_str(curproxy), curproxy->id,
8202 newsrv->id, sname);
8203 cfgerr++;
8204 goto next_srv;
8205 }
8206
Willy Tarreau32091232014-05-16 13:52:00 +02008207 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
8208 !(srv->agent.state & CHK_ST_CONFIGURED) &&
8209 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01008210 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02008211 "tracking as it does not have any check nor agent enabled.\n",
8212 proxy_type_str(curproxy), curproxy->id,
8213 newsrv->id, px->id, srv->id);
8214 cfgerr++;
8215 goto next_srv;
8216 }
8217
8218 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
8219
8220 if (loop) {
8221 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
8222 "belongs to a tracking chain looping back to %s/%s.\n",
8223 proxy_type_str(curproxy), curproxy->id,
8224 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008225 cfgerr++;
8226 goto next_srv;
8227 }
8228
8229 if (curproxy != px &&
8230 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
8231 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
8232 "tracking: disable-on-404 option inconsistency.\n",
8233 proxy_type_str(curproxy), curproxy->id,
8234 newsrv->id, px->id, srv->id);
8235 cfgerr++;
8236 goto next_srv;
8237 }
8238
8239 /* if the other server is forced disabled, we have to do the same here */
Willy Tarreau20125212014-05-13 19:44:56 +02008240 if (srv->admin & SRV_ADMF_MAINT) {
Willy Tarreaua0066dd2014-05-16 11:25:16 +02008241 newsrv->admin |= SRV_ADMF_IMAINT;
Willy Tarreau892337c2014-05-13 23:41:20 +02008242 newsrv->state = SRV_ST_STOPPED;
Simon Horman125d0992013-02-24 17:23:38 +09008243 newsrv->check.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008244 }
8245
8246 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01008247 newsrv->tracknext = srv->trackers;
8248 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008249
8250 free(newsrv->trackit);
8251 newsrv->trackit = NULL;
8252 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008253
8254 /*
8255 * resolve server's resolvers name and update the resolvers pointer
8256 * accordingly
8257 */
8258 if (newsrv->resolvers_id) {
8259 struct dns_resolvers *curr_resolvers;
8260 int found;
8261
8262 found = 0;
8263 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
8264 if (!strcmp(curr_resolvers->id, newsrv->resolvers_id)) {
8265 found = 1;
8266 break;
8267 }
8268 }
8269
8270 if (!found) {
8271 Alert("config : %s '%s', server '%s': unable to find required resolvers '%s'\n",
8272 proxy_type_str(curproxy), curproxy->id,
8273 newsrv->id, newsrv->resolvers_id);
8274 cfgerr++;
8275 } else {
8276 free(newsrv->resolvers_id);
8277 newsrv->resolvers_id = NULL;
8278 if (newsrv->resolution)
8279 newsrv->resolution->resolvers = curr_resolvers;
8280 }
8281 }
8282 else {
8283 /* if no resolvers section associated to this server
8284 * we can clean up the associated resolution structure
8285 */
8286 if (newsrv->resolution) {
8287 free(newsrv->resolution->hostname_dn);
8288 newsrv->resolution->hostname_dn = NULL;
8289 free(newsrv->resolution);
8290 newsrv->resolution = NULL;
8291 }
8292 }
8293
Willy Tarreau62c3be22012-01-20 13:12:32 +01008294 next_srv:
8295 newsrv = newsrv->next;
8296 }
8297
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008298 /* We have to initialize the server lookup mechanism depending
8299 * on what LB algorithm was choosen.
8300 */
8301
8302 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
8303 switch (curproxy->lbprm.algo & BE_LB_KIND) {
8304 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02008305 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
8306 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8307 init_server_map(curproxy);
8308 } else {
8309 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
8310 fwrr_init_server_groups(curproxy);
8311 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008312 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008313
Willy Tarreau3ebb1162012-02-13 16:57:44 +01008314 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01008315 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
8316 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
8317 fwlc_init_server_tree(curproxy);
8318 } else {
8319 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
8320 fas_init_server_tree(curproxy);
8321 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008322 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008323
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008324 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008325 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
8326 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
8327 chash_init_server_tree(curproxy);
8328 } else {
8329 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8330 init_server_map(curproxy);
8331 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008332 break;
8333 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02008334
8335 if (curproxy->options & PR_O_LOGASAP)
8336 curproxy->to_log &= ~LW_BYTES;
8337
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008338 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008339 (curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->logsrvs) &&
8340 (!LIST_ISEMPTY(&curproxy->logformat) || !LIST_ISEMPTY(&curproxy->logformat_sd))) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008341 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
8342 proxy_type_str(curproxy), curproxy->id);
8343 err_code |= ERR_WARN;
8344 }
8345
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008346 if (curproxy->mode != PR_MODE_HTTP) {
8347 int optnum;
8348
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008349 if (curproxy->uri_auth) {
8350 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
8351 proxy_type_str(curproxy), curproxy->id);
8352 err_code |= ERR_WARN;
8353 curproxy->uri_auth = NULL;
8354 }
8355
Willy Tarreau87cf5142011-08-19 22:57:24 +02008356 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008357 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8358 "forwardfor", proxy_type_str(curproxy), curproxy->id);
8359 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02008360 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008361 }
8362
8363 if (curproxy->options & PR_O_ORGTO) {
8364 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8365 "originalto", proxy_type_str(curproxy), curproxy->id);
8366 err_code |= ERR_WARN;
8367 curproxy->options &= ~PR_O_ORGTO;
8368 }
8369
8370 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
8371 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
8372 (curproxy->cap & cfg_opts[optnum].cap) &&
8373 (curproxy->options & cfg_opts[optnum].val)) {
8374 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8375 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
8376 err_code |= ERR_WARN;
8377 curproxy->options &= ~cfg_opts[optnum].val;
8378 }
8379 }
8380
8381 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
8382 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
8383 (curproxy->cap & cfg_opts2[optnum].cap) &&
8384 (curproxy->options2 & cfg_opts2[optnum].val)) {
8385 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8386 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
8387 err_code |= ERR_WARN;
8388 curproxy->options2 &= ~cfg_opts2[optnum].val;
8389 }
8390 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008391
Willy Tarreau29fbe512015-08-20 19:35:14 +02008392#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008393 if (curproxy->conn_src.bind_hdr_occ) {
8394 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008395 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01008396 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008397 err_code |= ERR_WARN;
8398 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008399#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008400 }
8401
Willy Tarreaubaaee002006-06-26 02:48:02 +02008402 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01008403 * ensure that we're not cross-dressing a TCP server into HTTP.
8404 */
8405 newsrv = curproxy->srv;
8406 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01008407 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008408 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
8409 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008410 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01008411 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008412
Willy Tarreau0cec3312011-10-31 13:49:26 +01008413 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
8414 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
8415 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8416 err_code |= ERR_WARN;
8417 }
8418
Willy Tarreauc93cd162014-05-13 15:54:22 +02008419 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02008420 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
8421 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8422 err_code |= ERR_WARN;
8423 }
8424
Willy Tarreau29fbe512015-08-20 19:35:14 +02008425#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008426 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
8427 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008428 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 +01008429 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008430 err_code |= ERR_WARN;
8431 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008432#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01008433 newsrv = newsrv->next;
8434 }
8435
Willy Tarreaue42bd962014-09-16 16:21:19 +02008436 /* check if we have a frontend with "tcp-request content" looking at L7
8437 * with no inspect-delay
8438 */
8439 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
8440 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008441 if (trule->action == ACT_TCP_CAPTURE &&
Thierry FOURNIERd0d65ae2015-08-04 08:21:12 +02008442 !(trule->arg.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008443 break;
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008444 if ((trule->action >= ACT_ACTION_TRK_SC0 && trule->action <= ACT_ACTION_TRK_SCMAX) &&
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008445 !(trule->arg.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008446 break;
8447 }
8448
8449 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
8450 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
8451 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
8452 " This means that these rules will randomly find their contents. This can be fixed by"
8453 " setting the tcp-request inspect-delay.\n",
8454 proxy_type_str(curproxy), curproxy->id);
8455 err_code |= ERR_WARN;
8456 }
8457 }
8458
Willy Tarreauc1a21672009-08-16 22:37:44 +02008459 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02008460 if (!curproxy->accept)
8461 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02008462
Willy Tarreauc1a21672009-08-16 22:37:44 +02008463 if (curproxy->tcp_req.inspect_delay ||
8464 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02008465 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008466
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008467 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008468 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008469 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008470 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008471
8472 /* both TCP and HTTP must check switching rules */
8473 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
8474 }
8475
8476 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02008477 if (curproxy->tcp_req.inspect_delay ||
8478 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
8479 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
8480
Emeric Brun97679e72010-09-23 17:56:44 +02008481 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
8482 curproxy->be_rsp_ana |= AN_RES_INSPECT;
8483
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008484 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008485 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008486 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008487 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008488
8489 /* If the backend does requires RDP cookie persistence, we have to
8490 * enable the corresponding analyser.
8491 */
8492 if (curproxy->options2 & PR_O2_RDPC_PRST)
8493 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
8494 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008495 }
8496
8497 /***********************************************************/
8498 /* At this point, target names have already been resolved. */
8499 /***********************************************************/
8500
8501 /* Check multi-process mode compatibility */
8502
8503 if (global.nbproc > 1 && global.stats_fe) {
8504 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8505 unsigned long mask;
8506
8507 mask = nbits(global.nbproc);
8508 if (global.stats_fe->bind_proc)
8509 mask &= global.stats_fe->bind_proc;
8510
8511 if (bind_conf->bind_proc)
8512 mask &= bind_conf->bind_proc;
8513
8514 /* stop here if more than one process is used */
David Carliere6c39412015-07-02 07:00:17 +00008515 if (my_popcountl(mask) > 1)
Willy Tarreau419ead82014-09-16 13:41:21 +02008516 break;
8517 }
8518 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
8519 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");
8520 }
8521 }
8522
8523 /* Make each frontend inherit bind-process from its listeners when not specified. */
8524 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8525 if (curproxy->bind_proc)
8526 continue;
8527
8528 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8529 unsigned long mask;
8530
Willy Tarreaue428b082015-05-04 21:57:58 +02008531 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008532 curproxy->bind_proc |= mask;
8533 }
8534
8535 if (!curproxy->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008536 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008537 }
8538
8539 if (global.stats_fe) {
8540 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8541 unsigned long mask;
8542
Willy Tarreaue428b082015-05-04 21:57:58 +02008543 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008544 global.stats_fe->bind_proc |= mask;
8545 }
8546 if (!global.stats_fe->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008547 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008548 }
8549
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02008550 /* propagate bindings from frontends to backends. Don't do it if there
8551 * are any fatal errors as we must not call it with unresolved proxies.
8552 */
8553 if (!cfgerr) {
8554 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8555 if (curproxy->cap & PR_CAP_FE)
8556 propagate_processes(curproxy, NULL);
8557 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008558 }
8559
8560 /* Bind each unbound backend to all processes when not specified. */
8561 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8562 if (curproxy->bind_proc)
8563 continue;
Willy Tarreaue428b082015-05-04 21:57:58 +02008564 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008565 }
8566
8567 /*******************************************************/
8568 /* At this step, all proxies have a non-null bind_proc */
8569 /*******************************************************/
8570
8571 /* perform the final checks before creating tasks */
8572
8573 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8574 struct listener *listener;
8575 unsigned int next_id;
8576 int nbproc;
8577
David Carliere6c39412015-07-02 07:00:17 +00008578 nbproc = my_popcountl(curproxy->bind_proc & nbits(global.nbproc));
Willy Tarreauc1a21672009-08-16 22:37:44 +02008579
Emeric Brunc52962f2012-11-15 18:28:02 +01008580#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008581 /* Configure SSL for each bind line.
8582 * Note: if configuration fails at some point, the ->ctx member
8583 * remains NULL so that listeners can later detach.
8584 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008585 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008586 int alloc_ctx;
8587
Emeric Brunc52962f2012-11-15 18:28:02 +01008588 if (!bind_conf->is_ssl) {
8589 if (bind_conf->default_ctx) {
8590 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
8591 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
8592 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008593 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01008594 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008595 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02008596 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008597 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008598 cfgerr++;
8599 continue;
8600 }
8601
Emeric Brun8dc60392014-05-09 13:52:00 +02008602 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008603 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02008604 if (alloc_ctx == SHCTX_E_INIT_LOCK)
8605 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");
8606 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008607 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02008608 cfgerr++;
8609 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008610 }
8611
Emeric Brunfc0421f2012-09-07 17:30:07 +02008612 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008613 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008614
8615 /* initialize CA variables if the certificates generation is enabled */
8616 cfgerr += ssl_sock_load_ca(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008617 }
Emeric Brunc52962f2012-11-15 18:28:02 +01008618#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008619
Willy Tarreaue6b98942007-10-29 01:09:36 +01008620 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008621 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008622 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008623 if (!listener->luid) {
8624 /* listener ID not set, use automatic numbering with first
8625 * spare entry starting with next_luid.
8626 */
8627 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
8628 listener->conf.id.key = listener->luid = next_id;
8629 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008630 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01008631 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008632
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008633 /* enable separate counters */
8634 if (curproxy->options2 & PR_O2_SOCKSTAT) {
8635 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01008636 if (!listener->name)
8637 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008638 }
Willy Tarreau81796be2012-09-22 19:11:47 +02008639
Willy Tarreaue6b98942007-10-29 01:09:36 +01008640 if (curproxy->options & PR_O_TCP_NOLING)
8641 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02008642 if (!listener->maxconn)
8643 listener->maxconn = curproxy->maxconn;
8644 if (!listener->backlog)
8645 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01008646 if (!listener->maxaccept)
8647 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
8648
8649 /* we want to have an optimal behaviour on single process mode to
8650 * maximize the work at once, but in multi-process we want to keep
8651 * some fairness between processes, so we target half of the max
8652 * number of events to be balanced over all the processes the proxy
8653 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
8654 * used to disable the limit.
8655 */
8656 if (listener->maxaccept > 0) {
8657 if (nbproc > 1)
8658 listener->maxaccept = (listener->maxaccept + 1) / 2;
8659 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
8660 }
8661
Willy Tarreau9903f0e2015-04-04 18:50:31 +02008662 listener->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02008663 listener->handler = process_stream;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008664 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01008665 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01008666
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008667 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
8668 listener->options |= LI_O_TCP_RULES;
8669
Willy Tarreaude3041d2010-05-31 10:56:17 +02008670 if (curproxy->mon_mask.s_addr)
8671 listener->options |= LI_O_CHK_MONNET;
8672
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008673 /* smart accept mode is automatic in HTTP mode */
8674 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008675 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008676 !(curproxy->no_options2 & PR_O2_SMARTACC)))
8677 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01008678 }
8679
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008680 /* Release unused SSL configs */
8681 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8682 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008683 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008684#ifdef USE_OPENSSL
Christopher Faulet31af49d2015-06-09 17:29:50 +02008685 ssl_sock_free_ca(bind_conf);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008686 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008687 free(bind_conf->ca_file);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008688 free(bind_conf->ca_sign_file);
8689 free(bind_conf->ca_sign_pass);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008690 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02008691 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008692 free(bind_conf->crl_file);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008693 if(bind_conf->keys_ref) {
8694 free(bind_conf->keys_ref->filename);
8695 free(bind_conf->keys_ref->tlskeys);
8696 free(bind_conf->keys_ref);
8697 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008698#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008699 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008700
Willy Tarreau102df612014-05-07 23:56:38 +02008701 if (nbproc > 1) {
8702 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02008703 int count, maxproc = 0;
8704
8705 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
David Carliere6c39412015-07-02 07:00:17 +00008706 count = my_popcountl(bind_conf->bind_proc);
Willy Tarreaueb791e02014-09-16 15:11:04 +02008707 if (count > maxproc)
8708 maxproc = count;
8709 }
8710 /* backends have 0, frontends have 1 or more */
8711 if (maxproc != 1)
8712 Warning("Proxy '%s': in multi-process mode, stats will be"
8713 " limited to process assigned to the current request.\n",
8714 curproxy->id);
8715
Willy Tarreau102df612014-05-07 23:56:38 +02008716 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
8717 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
8718 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008719 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008720 }
Willy Tarreau102df612014-05-07 23:56:38 +02008721 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
8722 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
8723 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008724 }
8725 }
Willy Tarreau918ff602011-07-25 16:33:49 +02008726
8727 /* create the task associated with the proxy */
8728 curproxy->task = task_new();
8729 if (curproxy->task) {
8730 curproxy->task->context = curproxy;
8731 curproxy->task->process = manage_proxy;
8732 /* no need to queue, it will be done automatically if some
8733 * listener gets limited.
8734 */
8735 curproxy->task->expire = TICK_ETERNITY;
8736 } else {
8737 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
8738 curproxy->id);
8739 cfgerr++;
8740 }
Willy Tarreaub369a042014-09-16 13:21:03 +02008741 }
8742
Willy Tarreaufbb78422011-06-05 15:38:35 +02008743 /* automatically compute fullconn if not set. We must not do it in the
8744 * loop above because cross-references are not yet fully resolved.
8745 */
8746 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8747 /* If <fullconn> is not set, let's set it to 10% of the sum of
8748 * the possible incoming frontend's maxconns.
8749 */
8750 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
8751 struct proxy *fe;
8752 int total = 0;
8753
8754 /* sum up the number of maxconns of frontends which
8755 * reference this backend at least once or which are
8756 * the same one ('listen').
8757 */
8758 for (fe = proxy; fe; fe = fe->next) {
8759 struct switching_rule *rule;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008760 int found = 0;
8761
8762 if (!(fe->cap & PR_CAP_FE))
8763 continue;
8764
8765 if (fe == curproxy) /* we're on a "listen" instance */
8766 found = 1;
8767
8768 if (fe->defbe.be == curproxy) /* "default_backend" */
8769 found = 1;
8770
8771 /* check if a "use_backend" rule matches */
8772 if (!found) {
8773 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01008774 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02008775 found = 1;
8776 break;
8777 }
8778 }
8779 }
8780
Willy Tarreaufbb78422011-06-05 15:38:35 +02008781 /* now we've checked all possible ways to reference a backend
8782 * from a frontend.
8783 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02008784 if (!found)
8785 continue;
8786 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008787 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02008788 /* we have the sum of the maxconns in <total>. We only
8789 * keep 10% of that sum to set the default fullconn, with
8790 * a hard minimum of 1 (to avoid a divide by zero).
8791 */
8792 curproxy->fullconn = (total + 9) / 10;
8793 if (!curproxy->fullconn)
8794 curproxy->fullconn = 1;
8795 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01008796 }
8797
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008798 /*
8799 * Recount currently required checks.
8800 */
8801
8802 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
8803 int optnum;
8804
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008805 for (optnum = 0; cfg_opts[optnum].name; optnum++)
8806 if (curproxy->options & cfg_opts[optnum].val)
8807 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008808
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008809 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
8810 if (curproxy->options2 & cfg_opts2[optnum].val)
8811 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008812 }
8813
Willy Tarreau0fca4832015-05-01 19:12:05 +02008814 /* compute the required process bindings for the peers */
8815 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
8816 if (curproxy->table.peers.p)
8817 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
8818
Willy Tarreau122541c2011-09-07 21:24:49 +02008819 if (peers) {
8820 struct peers *curpeers = peers, **last;
8821 struct peer *p, *pb;
8822
Willy Tarreau1e273012015-05-01 19:15:17 +02008823 /* Remove all peers sections which don't have a valid listener,
8824 * which are not used by any table, or which are bound to more
8825 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02008826 */
8827 last = &peers;
8828 while (*last) {
8829 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008830
8831 if (curpeers->state == PR_STSTOPPED) {
8832 /* the "disabled" keyword was present */
8833 if (curpeers->peers_fe)
8834 stop_proxy(curpeers->peers_fe);
8835 curpeers->peers_fe = NULL;
8836 }
8837 else if (!curpeers->peers_fe) {
8838 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
8839 curpeers->id, localpeer);
8840 }
David Carliere6c39412015-07-02 07:00:17 +00008841 else if (my_popcountl(curpeers->peers_fe->bind_proc) != 1) {
Willy Tarreau1e273012015-05-01 19:15:17 +02008842 /* either it's totally stopped or too much used */
8843 if (curpeers->peers_fe->bind_proc) {
8844 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreau64c57222015-05-04 21:48:51 +02008845 "running in different processes (%d different ones). "
8846 "Check global.nbproc and all tables' bind-process "
David Carliere6c39412015-07-02 07:00:17 +00008847 "settings.\n", curpeers->id, my_popcountl(curpeers->peers_fe->bind_proc));
Willy Tarreau1e273012015-05-01 19:15:17 +02008848 cfgerr++;
8849 }
8850 stop_proxy(curpeers->peers_fe);
8851 curpeers->peers_fe = NULL;
8852 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008853 else {
Emeric Brunb3971ab2015-05-12 18:49:09 +02008854 peers_init_sync(curpeers);
Willy Tarreau122541c2011-09-07 21:24:49 +02008855 last = &curpeers->next;
8856 continue;
8857 }
8858
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008859 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02008860 p = curpeers->remote;
8861 while (p) {
8862 pb = p->next;
8863 free(p->id);
8864 free(p);
8865 p = pb;
8866 }
8867
8868 /* Destroy and unlink this curpeers section.
8869 * Note: curpeers is backed up into *last.
8870 */
8871 free(curpeers->id);
8872 curpeers = curpeers->next;
8873 free(*last);
8874 *last = curpeers;
8875 }
8876 }
8877
Willy Tarreau6866f3f2015-05-01 19:09:08 +02008878 /* initialize stick-tables on backend capable proxies. This must not
8879 * be done earlier because the data size may be discovered while parsing
8880 * other proxies.
8881 */
8882 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8883 if (curproxy->state == PR_STSTOPPED)
8884 continue;
8885
8886 if (!stktable_init(&curproxy->table)) {
8887 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
8888 cfgerr++;
8889 }
8890 }
8891
Simon Horman0d16a402015-01-30 11:22:58 +09008892 if (mailers) {
8893 struct mailers *curmailers = mailers, **last;
8894 struct mailer *m, *mb;
8895
8896 /* Remove all mailers sections which don't have a valid listener.
8897 * This can happen when a mailers section is never referenced.
8898 */
8899 last = &mailers;
8900 while (*last) {
8901 curmailers = *last;
8902 if (curmailers->users) {
8903 last = &curmailers->next;
8904 continue;
8905 }
8906
8907 Warning("Removing incomplete section 'mailers %s'.\n",
8908 curmailers->id);
8909
8910 m = curmailers->mailer_list;
8911 while (m) {
8912 mb = m->next;
8913 free(m->id);
8914 free(m);
8915 m = mb;
8916 }
8917
8918 /* Destroy and unlink this curmailers section.
8919 * Note: curmailers is backed up into *last.
8920 */
8921 free(curmailers->id);
8922 curmailers = curmailers->next;
8923 free(*last);
8924 *last = curmailers;
8925 }
8926 }
8927
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02008928 /* Update server_state_file_name to backend name if backend is supposed to use
8929 * a server-state file locally defined and none has been provided */
8930 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8931 if (curproxy->load_server_state_from_file == PR_SRV_STATE_FILE_LOCAL &&
8932 curproxy->server_state_file_name == NULL)
8933 curproxy->server_state_file_name = strdup(curproxy->id);
8934 }
8935
Willy Tarreau34eb6712011-10-24 18:15:04 +02008936 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02008937 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02008938 MEM_F_SHARED);
8939
Willy Tarreaubb925012009-07-23 13:36:36 +02008940 if (cfgerr > 0)
8941 err_code |= ERR_ALERT | ERR_FATAL;
8942 out:
8943 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02008944}
8945
Willy Tarreau5b2c3362008-07-09 19:39:06 +02008946/*
8947 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
8948 * parsing sessions.
8949 */
8950void cfg_register_keywords(struct cfg_kw_list *kwl)
8951{
8952 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
8953}
Willy Tarreaubaaee002006-06-26 02:48:02 +02008954
Willy Tarreau5b2c3362008-07-09 19:39:06 +02008955/*
8956 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
8957 */
8958void cfg_unregister_keywords(struct cfg_kw_list *kwl)
8959{
8960 LIST_DEL(&kwl->list);
8961 LIST_INIT(&kwl->list);
8962}
Willy Tarreaubaaee002006-06-26 02:48:02 +02008963
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01008964/* this function register new section in the haproxy configuration file.
8965 * <section_name> is the name of this new section and <section_parser>
8966 * is the called parser. If two section declaration have the same name,
8967 * only the first declared is used.
8968 */
8969int cfg_register_section(char *section_name,
8970 int (*section_parser)(const char *, int, char **, int))
8971{
8972 struct cfg_section *cs;
8973
8974 cs = calloc(1, sizeof(*cs));
8975 if (!cs) {
8976 Alert("register section '%s': out of memory.\n", section_name);
8977 return 0;
8978 }
8979
8980 cs->section_name = section_name;
8981 cs->section_parser = section_parser;
8982
8983 LIST_ADDQ(&sections, &cs->list);
8984
8985 return 1;
8986}
8987
Willy Tarreaubaaee002006-06-26 02:48:02 +02008988/*
David Carlier845efb52015-09-25 11:49:18 +01008989 * free all config section entries
8990 */
8991void cfg_unregister_sections(void)
8992{
8993 struct cfg_section *cs, *ics;
8994
8995 list_for_each_entry_safe(cs, ics, &sections, list) {
8996 LIST_DEL(&cs->list);
8997 free(cs);
8998 }
8999}
9000
9001/*
Willy Tarreaubaaee002006-06-26 02:48:02 +02009002 * Local variables:
9003 * c-indent-level: 8
9004 * c-basic-offset: 8
9005 * End:
9006 */