blob: 71d3fea23945877e577974bc2887c38c8e5f5013 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreauff011f22011-01-06 17:51:27 +01004 * Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
Cyril Bonté1a0191d2014-08-29 20:20:02 +020013#ifdef CONFIG_HAP_CRYPT
14/* This is to have crypt() defined on Linux */
15#define _GNU_SOURCE
16
17#ifdef NEED_CRYPT_H
18/* some platforms such as Solaris need this */
19#include <crypt.h>
20#endif
21#endif /* CONFIG_HAP_CRYPT */
22
Willy Tarreaubaaee002006-06-26 02:48:02 +020023#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <netdb.h>
27#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020028#include <pwd.h>
29#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020030#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020031#include <sys/types.h>
32#include <sys/stat.h>
33#include <fcntl.h>
34#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
Willy Tarreau2dd0d472006-06-29 17:53:05 +020036#include <common/cfgparse.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020037#include <common/chunk.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020038#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020039#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020040#include <common/memory.h>
41#include <common/standard.h>
42#include <common/time.h>
43#include <common/uri_auth.h>
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +010044#include <common/namespace.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020045
46#include <types/capture.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020047#include <types/compression.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020048#include <types/global.h>
Willy Tarreau3fdb3662012-11-12 00:42:33 +010049#include <types/obj_type.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020050#include <types/peers.h>
Simon Horman0d16a402015-01-30 11:22:58 +090051#include <types/mailers.h>
Baptiste Assmann325137d2015-04-13 23:40:55 +020052#include <types/dns.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020053
Willy Tarreaueb0c6142007-05-07 00:53:22 +020054#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010055#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020056#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020057#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020058#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020059#include <proto/compression.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020060#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020061#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020062#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020063#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010064#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020065#include <proto/lb_fwlc.h>
66#include <proto/lb_fwrr.h>
67#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020068#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020069#include <proto/log.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020070#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010071#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020072#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010073#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010074#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020075#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020076#include <proto/sample.h>
Willy Tarreau9903f0e2015-04-04 18:50:31 +020077#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020078#include <proto/server.h>
Willy Tarreau87b09662015-04-03 00:22:06 +020079#include <proto/stream.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020080#include <proto/raw_sock.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020081#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010082#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020083
Emeric Brunfc0421f2012-09-07 17:30:07 +020084#ifdef USE_OPENSSL
85#include <types/ssl_sock.h>
86#include <proto/ssl_sock.h>
87#include <proto/shctx.h>
88#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020089
Willy Tarreauf3c69202006-07-09 16:42:34 +020090/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
91 * ssl-hello-chk option to ensure that the remote server speaks SSL.
92 *
93 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
94 */
95const char sslv3_client_hello_pkt[] = {
96 "\x16" /* ContentType : 0x16 = Hanshake */
97 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
98 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
99 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
100 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
101 "\x03\x00" /* Hello Version : 0x0300 = v3 */
102 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
103 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
104 "\x00" /* Session ID length : empty (no session ID) */
105 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
106 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
107 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
108 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
109 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
110 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
111 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
112 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
113 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
114 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
115 "\x00\x38" "\x00\x39" "\x00\x3A"
116 "\x01" /* Compression Length : 0x01 = 1 byte for types */
117 "\x00" /* Compression Type : 0x00 = NULL compression */
118};
119
Willy Tarreau3842f002009-06-14 11:39:52 +0200120/* various keyword modifiers */
121enum kw_mod {
122 KWM_STD = 0, /* normal */
123 KWM_NO, /* "no" prefixed before the keyword */
124 KWM_DEF, /* "default" prefixed before the keyword */
125};
126
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +0100127/* permit to store configuration section */
128struct cfg_section {
129 struct list list;
130 char *section_name;
131 int (*section_parser)(const char *, int, char **, int);
132};
133
134/* Used to chain configuration sections definitions. This list
135 * stores struct cfg_section
136 */
137struct list sections = LIST_HEAD_INIT(sections);
138
Willy Tarreau13943ab2006-12-31 00:24:10 +0100139/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100140struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100141 const char *name;
142 unsigned int val;
143 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100144 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100145 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100146};
147
148/* proxy->options */
149static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100150{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100151 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
152 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
153 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
154 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
155 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
156 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100157 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau9fbe18e2015-05-01 22:42:08 +0200158 { "http-buffer-request", PR_O_WREQ_BODY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau0f228a02015-05-01 15:37:53 +0200159 { "http-ignore-probes", PR_O_IGNORE_PRB, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreau9420b122013-12-15 18:58:25 +0100160 { "prefer-last-server", PR_O_PREF_LAST, PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100161 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
162 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
163 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100164 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100165#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100166 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100167#else
168 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100169#endif
170
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100171 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100172};
173
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100174/* proxy->options2 */
175static const struct cfg_opt cfg_opts2[] =
176{
177#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100178 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
179 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
180 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100181#else
182 { "splice-request", 0, 0, 0, 0 },
183 { "splice-response", 0, 0, 0, 0 },
184 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100185#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100186 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
187 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
188 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
189 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
190 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
191 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
192 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
193 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
194 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400195 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100196 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200197 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200198 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100199 { NULL, 0, 0, 0 }
200};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200201
Willy Tarreau6daf3432008-01-22 16:44:08 +0100202static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200203static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
204int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100205int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200206
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200207/* List head of all known configuration keywords */
208static struct cfg_kw_list cfg_keywords = {
209 .list = LIST_HEAD_INIT(cfg_keywords.list)
210};
211
Willy Tarreaubaaee002006-06-26 02:48:02 +0200212/*
213 * converts <str> to a list of listeners which are dynamically allocated.
214 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
215 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
216 * - <port> is a numerical port from 1 to 65535 ;
217 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
218 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200219 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
220 * not NULL, it must be a valid pointer to either NULL or a freeable area that
221 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200222 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200223int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf, const char *file, int line, char **err)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200224{
225 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100226 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200227 int port, end;
228
229 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200230
Willy Tarreaubaaee002006-06-26 02:48:02 +0200231 while (next && *next) {
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100232 struct sockaddr_storage ss, *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100233 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200234
235 str = next;
236 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100237 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200238 *next++ = 0;
239 }
240
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100241 ss2 = str2sa_range(str, &port, &end, err,
Willy Tarreau72b8c1f2015-09-08 15:50:19 +0200242 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix,
243 NULL);
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100244 if (!ss2)
245 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200246
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100247 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100248 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200249 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100250 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200251 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200252
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100253 if (!port || !end) {
254 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
255 goto fail;
256 }
257
Emeric Bruned760922010-10-22 17:59:25 +0200258 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200259 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200260 goto fail;
261 }
262
263 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200264 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200265 goto fail;
266 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200267 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100268 else if (ss2->ss_family == AF_UNSPEC) {
269 socklen_t addr_len;
270
271 /* We want to attach to an already bound fd whose number
272 * is in the addr part of ss2 when cast to sockaddr_in.
273 * Note that by definition there is a single listener.
274 * We still have to determine the address family to
275 * register the correct protocol.
276 */
277 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
278 addr_len = sizeof(*ss2);
279 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
280 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
281 goto fail;
282 }
283
284 port = end = get_host_port(ss2);
285 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200286
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100287 /* OK the address looks correct */
288 ss = *ss2;
289
Willy Tarreaubaaee002006-06-26 02:48:02 +0200290 for (; port <= end; port++) {
291 l = (struct listener *)calloc(1, sizeof(struct listener));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100292 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200293 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
294 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
295 l->frontend = curproxy;
296 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200297
Willy Tarreau40aa0702013-03-10 23:51:38 +0100298 l->fd = fd;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200299 l->addr = ss;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200300 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100301 l->state = LI_INIT;
302
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100303 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200304 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100305 tcpv4_add_listener(l);
306 }
Emeric Bruned760922010-10-22 17:59:25 +0200307 else if (ss.ss_family == AF_INET6) {
308 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
309 tcpv6_add_listener(l);
310 }
311 else {
Emeric Bruned760922010-10-22 17:59:25 +0200312 uxst_add_listener(l);
313 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200314
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200315 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100316 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200317 } /* end for(port) */
318 } /* end while(next) */
319 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200320 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200321 fail:
322 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200323 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200324}
325
William Lallemand6e62fb62015-04-28 16:55:23 +0200326/*
327 * Report a fatal Alert when there is too much arguments
328 * The index is the current keyword in args
329 * Return 0 if the number of argument is correct, otherwise emit an alert and return 1
330 * Fill err_code with an ERR_ALERT and an ERR_FATAL
331 */
332int alertif_too_many_args_idx(int maxarg, int index, const char *file, int linenum, char **args, int *err_code)
333{
334 char *kw = NULL;
335 int i;
336
337 if (!*args[index + maxarg + 1])
338 return 0;
339
340 memprintf(&kw, "%s", args[0]);
341 for (i = 1; i <= index; i++) {
342 memprintf(&kw, "%s %s", kw, args[i]);
343 }
344
345 Alert("parsing [%s:%d] : '%s' cannot handle unexpected argument '%s'.\n", file, linenum, kw, args[index + maxarg + 1]);
346 free(kw);
347 *err_code |= ERR_ALERT | ERR_FATAL;
348 return 1;
349}
350
351/*
352 * same as alertif_too_many_args_idx with a 0 index
353 */
354int alertif_too_many_args(int maxarg, const char *file, int linenum, char **args, int *err_code)
355{
356 return alertif_too_many_args_idx(maxarg, 0, file, linenum, args, err_code);
357}
358
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200359/* Report a warning if a rule is placed after a 'tcp-request content' rule.
360 * Return 1 if the warning has been emitted, otherwise 0.
361 */
362int warnif_rule_after_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
363{
364 if (!LIST_ISEMPTY(&proxy->tcp_req.inspect_rules)) {
365 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request content' rule will still be processed before.\n",
366 file, line, arg);
367 return 1;
368 }
369 return 0;
370}
371
Willy Tarreau61d18892009-03-31 10:49:21 +0200372/* Report a warning if a rule is placed after a 'block' rule.
373 * Return 1 if the warning has been emitted, otherwise 0.
374 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100375int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200376{
Willy Tarreau353bc9f2014-04-28 22:05:31 +0200377 if (!LIST_ISEMPTY(&proxy->block_rules)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200378 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
379 file, line, arg);
380 return 1;
381 }
382 return 0;
383}
384
Willy Tarreau5002f572014-04-23 01:32:02 +0200385/* Report a warning if a rule is placed after an 'http_request' rule.
386 * Return 1 if the warning has been emitted, otherwise 0.
387 */
388int warnif_rule_after_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
389{
390 if (!LIST_ISEMPTY(&proxy->http_req_rules)) {
391 Warning("parsing [%s:%d] : a '%s' rule placed after an 'http-request' rule will still be processed before.\n",
392 file, line, arg);
393 return 1;
394 }
395 return 0;
396}
397
Willy Tarreau61d18892009-03-31 10:49:21 +0200398/* Report a warning if a rule is placed after a reqrewrite rule.
399 * Return 1 if the warning has been emitted, otherwise 0.
400 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100401int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200402{
403 if (proxy->req_exp) {
404 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
405 file, line, arg);
406 return 1;
407 }
408 return 0;
409}
410
411/* Report a warning if a rule is placed after a reqadd rule.
412 * Return 1 if the warning has been emitted, otherwise 0.
413 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100414int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200415{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100416 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200417 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
418 file, line, arg);
419 return 1;
420 }
421 return 0;
422}
423
424/* Report a warning if a rule is placed after a redirect rule.
425 * Return 1 if the warning has been emitted, otherwise 0.
426 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100427int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200428{
429 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
430 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
431 file, line, arg);
432 return 1;
433 }
434 return 0;
435}
436
437/* Report a warning if a rule is placed after a 'use_backend' rule.
438 * Return 1 if the warning has been emitted, otherwise 0.
439 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100440int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200441{
442 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
443 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
444 file, line, arg);
445 return 1;
446 }
447 return 0;
448}
449
Willy Tarreauee445d92014-04-23 01:39:04 +0200450/* Report a warning if a rule is placed after a 'use-server' rule.
451 * Return 1 if the warning has been emitted, otherwise 0.
452 */
453int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line, const char *arg)
454{
455 if (!LIST_ISEMPTY(&proxy->server_rules)) {
456 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use-server' rule will still be processed before.\n",
457 file, line, arg);
458 return 1;
459 }
460 return 0;
461}
462
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200463/* report a warning if a "tcp request connection" rule is dangerously placed */
464int warnif_misplaced_tcp_conn(struct proxy *proxy, const char *file, int line, const char *arg)
465{
466 return warnif_rule_after_tcp_cont(proxy, file, line, arg) ||
467 warnif_rule_after_block(proxy, file, line, arg) ||
468 warnif_rule_after_http_req(proxy, file, line, arg) ||
469 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
470 warnif_rule_after_reqadd(proxy, file, line, arg) ||
471 warnif_rule_after_redirect(proxy, file, line, arg) ||
472 warnif_rule_after_use_backend(proxy, file, line, arg) ||
473 warnif_rule_after_use_server(proxy, file, line, arg);
474}
475
476/* report a warning if a "tcp request content" rule is dangerously placed */
477int warnif_misplaced_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
478{
479 return warnif_rule_after_block(proxy, file, line, arg) ||
480 warnif_rule_after_http_req(proxy, file, line, arg) ||
481 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
482 warnif_rule_after_reqadd(proxy, file, line, arg) ||
483 warnif_rule_after_redirect(proxy, file, line, arg) ||
484 warnif_rule_after_use_backend(proxy, file, line, arg) ||
485 warnif_rule_after_use_server(proxy, file, line, arg);
486}
487
Willy Tarreau61d18892009-03-31 10:49:21 +0200488/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100489int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200490{
Willy Tarreau5002f572014-04-23 01:32:02 +0200491 return warnif_rule_after_http_req(proxy, file, line, arg) ||
492 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
493 warnif_rule_after_reqadd(proxy, file, line, arg) ||
494 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200495 warnif_rule_after_use_backend(proxy, file, line, arg) ||
496 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau5002f572014-04-23 01:32:02 +0200497}
498
499/* report a warning if an http-request rule is dangerously placed */
500int warnif_misplaced_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
501{
Willy Tarreau61d18892009-03-31 10:49:21 +0200502 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
503 warnif_rule_after_reqadd(proxy, file, line, arg) ||
504 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200505 warnif_rule_after_use_backend(proxy, file, line, arg) ||
506 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200507}
508
509/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100510int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200511{
512 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
513 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200514 warnif_rule_after_use_backend(proxy, file, line, arg) ||
515 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200516}
517
518/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100519int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200520{
521 return warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200522 warnif_rule_after_use_backend(proxy, file, line, arg) ||
523 warnif_rule_after_use_server(proxy, file, line, arg);
524}
525
526/* report a warning if a redirect rule is dangerously placed */
527int warnif_misplaced_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
528{
529 return warnif_rule_after_use_backend(proxy, file, line, arg) ||
530 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200531}
532
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100533/* Report it if a request ACL condition uses some keywords that are incompatible
534 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
535 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
536 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100537 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100538static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100539{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100540 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200541 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100542
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100543 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100544 return 0;
545
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100546 acl = acl_cond_conflicts(cond, where);
547 if (acl) {
548 if (acl->name && *acl->name)
549 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
550 file, line, acl->name, sample_ckp_names(where));
551 else
552 Warning("parsing [%s:%d] : anonymous acl will never match because it uses keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200553 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100554 return ERR_WARN;
555 }
556 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100557 return 0;
558
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100559 if (acl->name && *acl->name)
560 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200561 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100562 else
563 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200564 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100565 return ERR_WARN;
566}
567
Willy Tarreaubaaee002006-06-26 02:48:02 +0200568/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200569 * parse a line in a <global> section. Returns the error code, 0 if OK, or
570 * any combination of :
571 * - ERR_ABORT: must abort ASAP
572 * - ERR_FATAL: we can continue parsing but not start the service
573 * - ERR_WARN: a warning has been emitted
574 * - ERR_ALERT: an alert has been emitted
575 * Only the two first ones can stop processing, the two others are just
576 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200577 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200578int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200579{
Willy Tarreau058e9072009-07-20 09:30:05 +0200580 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200581 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200582
583 if (!strcmp(args[0], "global")) { /* new section */
584 /* no option, nothing special to do */
William Lallemand6e62fb62015-04-28 16:55:23 +0200585 alertif_too_many_args(0, file, linenum, args, &err_code);
Willy Tarreau058e9072009-07-20 09:30:05 +0200586 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200587 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200588 else if (!strcmp(args[0], "ca-base")) {
589#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +0200590 if(alertif_too_many_args(1, file, linenum, args, &err_code))
591 goto out;
Emeric Brunc8e8d122012-10-02 18:42:10 +0200592 if (global.ca_base != NULL) {
593 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
594 err_code |= ERR_ALERT;
595 goto out;
596 }
597 if (*(args[1]) == 0) {
598 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
599 err_code |= ERR_ALERT | ERR_FATAL;
600 goto out;
601 }
602 global.ca_base = strdup(args[1]);
603#else
604 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
605 err_code |= ERR_ALERT | ERR_FATAL;
606 goto out;
607#endif
608 }
609 else if (!strcmp(args[0], "crt-base")) {
610#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +0200611 if (alertif_too_many_args(1, file, linenum, args, &err_code))
612 goto out;
Emeric Brunc8e8d122012-10-02 18:42:10 +0200613 if (global.crt_base != NULL) {
614 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
615 err_code |= ERR_ALERT;
616 goto out;
617 }
618 if (*(args[1]) == 0) {
619 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
620 err_code |= ERR_ALERT | ERR_FATAL;
621 goto out;
622 }
623 global.crt_base = strdup(args[1]);
624#else
625 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
626 err_code |= ERR_ALERT | ERR_FATAL;
627 goto out;
628#endif
629 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200630 else if (!strcmp(args[0], "daemon")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200631 if (alertif_too_many_args(0, file, linenum, args, &err_code))
632 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200633 global.mode |= MODE_DAEMON;
634 }
635 else if (!strcmp(args[0], "debug")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200636 if (alertif_too_many_args(0, file, linenum, args, &err_code))
637 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200638 global.mode |= MODE_DEBUG;
639 }
640 else if (!strcmp(args[0], "noepoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200641 if (alertif_too_many_args(0, file, linenum, args, &err_code))
642 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100643 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200644 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200645 else if (!strcmp(args[0], "nokqueue")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200646 if (alertif_too_many_args(0, file, linenum, args, &err_code))
647 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100648 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200649 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200650 else if (!strcmp(args[0], "nopoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200651 if (alertif_too_many_args(0, file, linenum, args, &err_code))
652 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100653 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200654 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100655 else if (!strcmp(args[0], "nosplice")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200656 if (alertif_too_many_args(0, file, linenum, args, &err_code))
657 goto out;
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100658 global.tune.options &= ~GTUNE_USE_SPLICE;
659 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200660 else if (!strcmp(args[0], "nogetaddrinfo")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200661 if (alertif_too_many_args(0, file, linenum, args, &err_code))
662 goto out;
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200663 global.tune.options &= ~GTUNE_USE_GAI;
664 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200665 else if (!strcmp(args[0], "quiet")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200666 if (alertif_too_many_args(0, file, linenum, args, &err_code))
667 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200668 global.mode |= MODE_QUIET;
669 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200670 else if (!strcmp(args[0], "tune.maxpollevents")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200671 if (alertif_too_many_args(1, file, linenum, args, &err_code))
672 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200673 if (global.tune.maxpollevents != 0) {
674 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200675 err_code |= ERR_ALERT;
676 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200677 }
678 if (*(args[1]) == 0) {
679 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200680 err_code |= ERR_ALERT | ERR_FATAL;
681 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200682 }
683 global.tune.maxpollevents = atol(args[1]);
684 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100685 else if (!strcmp(args[0], "tune.maxaccept")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200686 if (alertif_too_many_args(1, file, linenum, args, &err_code))
687 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100688 if (global.tune.maxaccept != 0) {
689 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200690 err_code |= ERR_ALERT;
691 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100692 }
693 if (*(args[1]) == 0) {
694 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200695 err_code |= ERR_ALERT | ERR_FATAL;
696 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100697 }
698 global.tune.maxaccept = atol(args[1]);
699 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200700 else if (!strcmp(args[0], "tune.chksize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200701 if (alertif_too_many_args(1, file, linenum, args, &err_code))
702 goto out;
Willy Tarreau43961d52010-10-04 20:39:20 +0200703 if (*(args[1]) == 0) {
704 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
705 err_code |= ERR_ALERT | ERR_FATAL;
706 goto out;
707 }
708 global.tune.chksize = atol(args[1]);
709 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200710#ifdef USE_OPENSSL
Emeric Brun8dc60392014-05-09 13:52:00 +0200711 else if (!strcmp(args[0], "tune.ssl.force-private-cache")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200712 if (alertif_too_many_args(0, file, linenum, args, &err_code))
713 goto out;
Emeric Brun8dc60392014-05-09 13:52:00 +0200714 global.tune.sslprivatecache = 1;
715 }
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100716 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200717 if (alertif_too_many_args(1, file, linenum, args, &err_code))
718 goto out;
Emeric Brunfc32aca2012-09-03 12:10:29 +0200719 if (*(args[1]) == 0) {
720 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
721 err_code |= ERR_ALERT | ERR_FATAL;
722 goto out;
723 }
724 global.tune.sslcachesize = atol(args[1]);
725 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100726 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
727 unsigned int ssllifetime;
728 const char *res;
729
William Lallemand1a748ae2015-05-19 16:37:23 +0200730 if (alertif_too_many_args(1, file, linenum, args, &err_code))
731 goto out;
Emeric Brun4f65bff2012-11-16 15:11:00 +0100732 if (*(args[1]) == 0) {
733 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
734 err_code |= ERR_ALERT | ERR_FATAL;
735 goto out;
736 }
737
738 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
739 if (res) {
740 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
741 file, linenum, *res, args[0]);
742 err_code |= ERR_ALERT | ERR_FATAL;
743 goto out;
744 }
745
746 global.tune.ssllifetime = ssllifetime;
747 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100748 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200749 if (alertif_too_many_args(1, file, linenum, args, &err_code))
750 goto out;
Willy Tarreaubfd59462013-02-21 07:46:09 +0100751 if (*(args[1]) == 0) {
752 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
753 err_code |= ERR_ALERT | ERR_FATAL;
754 goto out;
755 }
756 global.tune.ssl_max_record = atol(args[1]);
757 }
Remi Gacogne47783ef2015-05-29 15:53:22 +0200758#ifndef OPENSSL_NO_DH
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200759 else if (!strcmp(args[0], "tune.ssl.default-dh-param")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200760 if (alertif_too_many_args(1, file, linenum, args, &err_code))
761 goto out;
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200762 if (*(args[1]) == 0) {
763 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
764 err_code |= ERR_ALERT | ERR_FATAL;
765 goto out;
766 }
767 global.tune.ssl_default_dh_param = atol(args[1]);
768 if (global.tune.ssl_default_dh_param < 1024) {
769 Alert("parsing [%s:%d] : '%s' expects a value >= 1024.\n", file, linenum, args[0]);
770 err_code |= ERR_ALERT | ERR_FATAL;
771 goto out;
772 }
773 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200774#endif
Christopher Faulet31af49d2015-06-09 17:29:50 +0200775 else if (!strcmp(args[0], "tune.ssl.ssl-ctx-cache-size")) {
776 if (alertif_too_many_args(1, file, linenum, args, &err_code))
777 goto out;
778 if (*(args[1]) == 0) {
779 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
780 err_code |= ERR_ALERT | ERR_FATAL;
781 goto out;
782 }
783 global.tune.ssl_ctx_cache = atoi(args[1]);
784 if (global.tune.ssl_ctx_cache < 0) {
785 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
786 file, linenum, args[0]);
787 err_code |= ERR_ALERT | ERR_FATAL;
788 goto out;
789 }
790 }
Remi Gacogne47783ef2015-05-29 15:53:22 +0200791#endif
Willy Tarreau33cb0652014-12-23 22:52:37 +0100792 else if (!strcmp(args[0], "tune.buffers.limit")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200793 if (alertif_too_many_args(1, file, linenum, args, &err_code))
794 goto out;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100795 if (*(args[1]) == 0) {
796 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
797 err_code |= ERR_ALERT | ERR_FATAL;
798 goto out;
799 }
800 global.tune.buf_limit = atol(args[1]);
801 if (global.tune.buf_limit) {
802 if (global.tune.buf_limit < 3)
803 global.tune.buf_limit = 3;
804 if (global.tune.buf_limit <= global.tune.reserved_bufs)
805 global.tune.buf_limit = global.tune.reserved_bufs + 1;
806 }
807 }
Willy Tarreau1058ae72014-12-23 22:40:40 +0100808 else if (!strcmp(args[0], "tune.buffers.reserve")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200809 if (alertif_too_many_args(1, file, linenum, args, &err_code))
810 goto out;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100811 if (*(args[1]) == 0) {
812 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
813 err_code |= ERR_ALERT | ERR_FATAL;
814 goto out;
815 }
816 global.tune.reserved_bufs = atol(args[1]);
817 if (global.tune.reserved_bufs < 2)
818 global.tune.reserved_bufs = 2;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100819 if (global.tune.buf_limit && global.tune.buf_limit <= global.tune.reserved_bufs)
820 global.tune.buf_limit = global.tune.reserved_bufs + 1;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100821 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200822 else if (!strcmp(args[0], "tune.bufsize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200823 if (alertif_too_many_args(1, file, linenum, args, &err_code))
824 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200825 if (*(args[1]) == 0) {
826 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
827 err_code |= ERR_ALERT | ERR_FATAL;
828 goto out;
829 }
830 global.tune.bufsize = atol(args[1]);
831 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
832 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100833 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100834 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200835 }
836 else if (!strcmp(args[0], "tune.maxrewrite")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200837 if (alertif_too_many_args(1, file, linenum, args, &err_code))
838 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200839 if (*(args[1]) == 0) {
840 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
841 err_code |= ERR_ALERT | ERR_FATAL;
842 goto out;
843 }
844 global.tune.maxrewrite = atol(args[1]);
845 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
846 global.tune.maxrewrite = global.tune.bufsize / 2;
847 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100848 else if (!strcmp(args[0], "tune.idletimer")) {
849 unsigned int idle;
850 const char *res;
851
William Lallemand1a748ae2015-05-19 16:37:23 +0200852 if (alertif_too_many_args(1, file, linenum, args, &err_code))
853 goto out;
Willy Tarreau7e312732014-02-12 16:35:14 +0100854 if (*(args[1]) == 0) {
855 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
856 err_code |= ERR_ALERT | ERR_FATAL;
857 goto out;
858 }
859
860 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
861 if (res) {
862 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
863 file, linenum, *res, args[0]);
864 err_code |= ERR_ALERT | ERR_FATAL;
865 goto out;
866 }
867
868 if (idle > 65535) {
869 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
870 err_code |= ERR_ALERT | ERR_FATAL;
871 goto out;
872 }
873 global.tune.idle_timer = idle;
874 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100875 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200876 if (alertif_too_many_args(1, file, linenum, args, &err_code))
877 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100878 if (global.tune.client_rcvbuf != 0) {
879 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
880 err_code |= ERR_ALERT;
881 goto out;
882 }
883 if (*(args[1]) == 0) {
884 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
885 err_code |= ERR_ALERT | ERR_FATAL;
886 goto out;
887 }
888 global.tune.client_rcvbuf = atol(args[1]);
889 }
890 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200891 if (alertif_too_many_args(1, file, linenum, args, &err_code))
892 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100893 if (global.tune.server_rcvbuf != 0) {
894 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
895 err_code |= ERR_ALERT;
896 goto out;
897 }
898 if (*(args[1]) == 0) {
899 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
900 err_code |= ERR_ALERT | ERR_FATAL;
901 goto out;
902 }
903 global.tune.server_rcvbuf = atol(args[1]);
904 }
905 else if (!strcmp(args[0], "tune.sndbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200906 if (alertif_too_many_args(1, file, linenum, args, &err_code))
907 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100908 if (global.tune.client_sndbuf != 0) {
909 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
910 err_code |= ERR_ALERT;
911 goto out;
912 }
913 if (*(args[1]) == 0) {
914 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
915 err_code |= ERR_ALERT | ERR_FATAL;
916 goto out;
917 }
918 global.tune.client_sndbuf = atol(args[1]);
919 }
920 else if (!strcmp(args[0], "tune.sndbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200921 if (alertif_too_many_args(1, file, linenum, args, &err_code))
922 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100923 if (global.tune.server_sndbuf != 0) {
924 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
925 err_code |= ERR_ALERT;
926 goto out;
927 }
928 if (*(args[1]) == 0) {
929 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
930 err_code |= ERR_ALERT | ERR_FATAL;
931 goto out;
932 }
933 global.tune.server_sndbuf = atol(args[1]);
934 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200935 else if (!strcmp(args[0], "tune.pipesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200936 if (alertif_too_many_args(1, file, linenum, args, &err_code))
937 goto out;
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200938 if (*(args[1]) == 0) {
939 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
940 err_code |= ERR_ALERT | ERR_FATAL;
941 goto out;
942 }
943 global.tune.pipesize = atol(args[1]);
944 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100945 else if (!strcmp(args[0], "tune.http.cookielen")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200946 if (alertif_too_many_args(1, file, linenum, args, &err_code))
947 goto out;
Willy Tarreau193b8c62012-11-22 00:17:38 +0100948 if (*(args[1]) == 0) {
949 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
950 err_code |= ERR_ALERT | ERR_FATAL;
951 goto out;
952 }
953 global.tune.cookie_len = atol(args[1]) + 1;
954 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200955 else if (!strcmp(args[0], "tune.http.maxhdr")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200956 if (alertif_too_many_args(1, file, linenum, args, &err_code))
957 goto out;
Willy Tarreauac1932d2011-10-24 19:14:41 +0200958 if (*(args[1]) == 0) {
959 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
960 err_code |= ERR_ALERT | ERR_FATAL;
961 goto out;
962 }
963 global.tune.max_http_hdr = atol(args[1]);
964 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100965 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
966#ifdef USE_ZLIB
William Lallemand1a748ae2015-05-19 16:37:23 +0200967 if (alertif_too_many_args(1, file, linenum, args, &err_code))
968 goto out;
William Lallemanda509e4c2012-11-07 16:54:34 +0100969 if (*args[1]) {
970 global.tune.zlibmemlevel = atoi(args[1]);
971 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
972 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
973 file, linenum, args[0]);
974 err_code |= ERR_ALERT | ERR_FATAL;
975 goto out;
976 }
977 } else {
978 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
979 file, linenum, args[0]);
980 err_code |= ERR_ALERT | ERR_FATAL;
981 goto out;
982 }
983#else
984 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
985 err_code |= ERR_ALERT | ERR_FATAL;
986 goto out;
987#endif
988 }
989 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
990#ifdef USE_ZLIB
William Lallemand1a748ae2015-05-19 16:37:23 +0200991 if (alertif_too_many_args(1, file, linenum, args, &err_code))
992 goto out;
William Lallemanda509e4c2012-11-07 16:54:34 +0100993 if (*args[1]) {
994 global.tune.zlibwindowsize = atoi(args[1]);
995 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
996 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
997 file, linenum, args[0]);
998 err_code |= ERR_ALERT | ERR_FATAL;
999 goto out;
1000 }
1001 } else {
1002 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
1003 file, linenum, args[0]);
1004 err_code |= ERR_ALERT | ERR_FATAL;
1005 goto out;
1006 }
1007#else
1008 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1009 err_code |= ERR_ALERT | ERR_FATAL;
1010 goto out;
1011#endif
1012 }
William Lallemandf3747832012-11-09 12:33:10 +01001013 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001014 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1015 goto out;
William Lallemandf3747832012-11-09 12:33:10 +01001016 if (*args[1]) {
1017 global.tune.comp_maxlevel = atoi(args[1]);
1018 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
1019 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1020 file, linenum, args[0]);
1021 err_code |= ERR_ALERT | ERR_FATAL;
1022 goto out;
1023 }
1024 } else {
1025 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1026 file, linenum, args[0]);
1027 err_code |= ERR_ALERT | ERR_FATAL;
1028 goto out;
1029 }
1030 }
Willy Tarreauf3045d22015-04-29 16:24:50 +02001031 else if (!strcmp(args[0], "tune.pattern.cache-size")) {
1032 if (*args[1]) {
1033 global.tune.pattern_cache = atoi(args[1]);
1034 if (global.tune.pattern_cache < 0) {
1035 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
1036 file, linenum, args[0]);
1037 err_code |= ERR_ALERT | ERR_FATAL;
1038 goto out;
1039 }
1040 } else {
1041 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
1042 file, linenum, args[0]);
1043 err_code |= ERR_ALERT | ERR_FATAL;
1044 goto out;
1045 }
1046 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001047 else if (!strcmp(args[0], "uid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001048 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1049 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001050 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001051 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001052 err_code |= ERR_ALERT;
1053 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001054 }
1055 if (*(args[1]) == 0) {
1056 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001057 err_code |= ERR_ALERT | ERR_FATAL;
1058 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001059 }
1060 global.uid = atol(args[1]);
1061 }
1062 else if (!strcmp(args[0], "gid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001063 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1064 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001065 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001066 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001067 err_code |= ERR_ALERT;
1068 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001069 }
1070 if (*(args[1]) == 0) {
1071 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001072 err_code |= ERR_ALERT | ERR_FATAL;
1073 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001074 }
1075 global.gid = atol(args[1]);
1076 }
Simon Horman98637e52014-06-20 12:30:16 +09001077 else if (!strcmp(args[0], "external-check")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001078 if (alertif_too_many_args(0, file, linenum, args, &err_code))
1079 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09001080 global.external_check = 1;
1081 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001082 /* user/group name handling */
1083 else if (!strcmp(args[0], "user")) {
1084 struct passwd *ha_user;
William Lallemand1a748ae2015-05-19 16:37:23 +02001085 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1086 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001087 if (global.uid != 0) {
1088 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001089 err_code |= ERR_ALERT;
1090 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001091 }
1092 errno = 0;
1093 ha_user = getpwnam(args[1]);
1094 if (ha_user != NULL) {
1095 global.uid = (int)ha_user->pw_uid;
1096 }
1097 else {
1098 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +02001099 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001100 }
1101 }
1102 else if (!strcmp(args[0], "group")) {
1103 struct group *ha_group;
William Lallemand1a748ae2015-05-19 16:37:23 +02001104 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1105 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001106 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02001107 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001108 err_code |= ERR_ALERT;
1109 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001110 }
1111 errno = 0;
1112 ha_group = getgrnam(args[1]);
1113 if (ha_group != NULL) {
1114 global.gid = (int)ha_group->gr_gid;
1115 }
1116 else {
1117 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +02001118 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001119 }
1120 }
1121 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +02001122 else if (!strcmp(args[0], "nbproc")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001123 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1124 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001125 if (*(args[1]) == 0) {
1126 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001127 err_code |= ERR_ALERT | ERR_FATAL;
1128 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001129 }
1130 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001131 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
1132 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
1133 file, linenum, args[0], LONGBITS, global.nbproc);
1134 err_code |= ERR_ALERT | ERR_FATAL;
1135 goto out;
1136 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001137 }
1138 else if (!strcmp(args[0], "maxconn")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001139 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1140 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001141 if (global.maxconn != 0) {
1142 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001143 err_code |= ERR_ALERT;
1144 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001145 }
1146 if (*(args[1]) == 0) {
1147 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001148 err_code |= ERR_ALERT | ERR_FATAL;
1149 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001150 }
1151 global.maxconn = atol(args[1]);
1152#ifdef SYSTEM_MAXCONN
1153 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
1154 Alert("parsing [%s:%d] : maxconn value %d too high for this system.\nLimiting to %d. Please use '-n' to force the value.\n", file, linenum, global.maxconn, DEFAULT_MAXCONN);
1155 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +02001156 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001157 }
1158#endif /* SYSTEM_MAXCONN */
1159 }
Willy Tarreau403edff2012-09-06 11:58:37 +02001160 else if (!strcmp(args[0], "maxsslconn")) {
1161#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001162 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1163 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001164 if (*(args[1]) == 0) {
1165 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1166 err_code |= ERR_ALERT | ERR_FATAL;
1167 goto out;
1168 }
1169 global.maxsslconn = atol(args[1]);
1170#else
Emeric Brun0914df82012-10-02 18:45:42 +02001171 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1172 err_code |= ERR_ALERT | ERR_FATAL;
1173 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001174#endif
1175 }
Willy Tarreau610f04b2014-02-13 11:36:41 +01001176 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
1177#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001178 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1179 goto out;
Willy Tarreau610f04b2014-02-13 11:36:41 +01001180 if (*(args[1]) == 0) {
1181 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1182 err_code |= ERR_ALERT | ERR_FATAL;
1183 goto out;
1184 }
1185 free(global.listen_default_ciphers);
1186 global.listen_default_ciphers = strdup(args[1]);
1187#else
1188 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1189 err_code |= ERR_ALERT | ERR_FATAL;
1190 goto out;
1191#endif
1192 }
1193 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
1194#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001195 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1196 goto out;
Willy Tarreau610f04b2014-02-13 11:36:41 +01001197 if (*(args[1]) == 0) {
1198 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1199 err_code |= ERR_ALERT | ERR_FATAL;
1200 goto out;
1201 }
1202 free(global.connect_default_ciphers);
1203 global.connect_default_ciphers = strdup(args[1]);
1204#else
1205 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1206 err_code |= ERR_ALERT | ERR_FATAL;
1207 goto out;
1208#endif
1209 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02001210#ifdef USE_OPENSSL
1211#ifndef OPENSSL_NO_DH
1212 else if (!strcmp(args[0], "ssl-dh-param-file")) {
1213 if (*(args[1]) == 0) {
1214 Alert("parsing [%s:%d] : '%s' expects a file path as an argument.\n", file, linenum, args[0]);
1215 err_code |= ERR_ALERT | ERR_FATAL;
1216 goto out;
1217 }
1218 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
1219 Alert("parsing [%s:%d] : '%s': unable to load DH parameters from file <%s>.\n", file, linenum, args[0], args[1]);
1220 err_code |= ERR_ALERT | ERR_FATAL;
1221 goto out;
1222 }
1223 }
1224#endif
1225#endif
Emeric Brun850efd52014-01-29 12:24:34 +01001226 else if (!strcmp(args[0], "ssl-server-verify")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001227 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1228 goto out;
Emeric Brun850efd52014-01-29 12:24:34 +01001229 if (*(args[1]) == 0) {
1230 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1231 err_code |= ERR_ALERT | ERR_FATAL;
1232 goto out;
1233 }
1234 if (strcmp(args[1],"none") == 0)
1235 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1236 else if (strcmp(args[1],"required") == 0)
1237 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1238 else {
1239 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1240 err_code |= ERR_ALERT | ERR_FATAL;
1241 goto out;
1242 }
1243 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001244 else if (!strcmp(args[0], "maxconnrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001245 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1246 goto out;
Willy Tarreau81c25d02011-09-07 15:17:21 +02001247 if (global.cps_lim != 0) {
1248 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1249 err_code |= ERR_ALERT;
1250 goto out;
1251 }
1252 if (*(args[1]) == 0) {
1253 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1254 err_code |= ERR_ALERT | ERR_FATAL;
1255 goto out;
1256 }
1257 global.cps_lim = atol(args[1]);
1258 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001259 else if (!strcmp(args[0], "maxsessrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001260 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1261 goto out;
Willy Tarreau93e7c002013-10-07 18:51:07 +02001262 if (global.sps_lim != 0) {
1263 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1264 err_code |= ERR_ALERT;
1265 goto out;
1266 }
1267 if (*(args[1]) == 0) {
1268 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1269 err_code |= ERR_ALERT | ERR_FATAL;
1270 goto out;
1271 }
1272 global.sps_lim = atol(args[1]);
1273 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001274 else if (!strcmp(args[0], "maxsslrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001275 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1276 goto out;
Willy Tarreaue43d5322013-10-07 20:01:52 +02001277 if (global.ssl_lim != 0) {
1278 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1279 err_code |= ERR_ALERT;
1280 goto out;
1281 }
1282 if (*(args[1]) == 0) {
1283 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1284 err_code |= ERR_ALERT | ERR_FATAL;
1285 goto out;
1286 }
1287 global.ssl_lim = atol(args[1]);
1288 }
William Lallemandd85f9172012-11-09 17:05:39 +01001289 else if (!strcmp(args[0], "maxcomprate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001290 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1291 goto out;
William Lallemandd85f9172012-11-09 17:05:39 +01001292 if (*(args[1]) == 0) {
1293 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1294 err_code |= ERR_ALERT | ERR_FATAL;
1295 goto out;
1296 }
1297 global.comp_rate_lim = atoi(args[1]) * 1024;
1298 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001299 else if (!strcmp(args[0], "maxpipes")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001300 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1301 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001302 if (global.maxpipes != 0) {
1303 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001304 err_code |= ERR_ALERT;
1305 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001306 }
1307 if (*(args[1]) == 0) {
1308 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001309 err_code |= ERR_ALERT | ERR_FATAL;
1310 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001311 }
1312 global.maxpipes = atol(args[1]);
1313 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001314 else if (!strcmp(args[0], "maxzlibmem")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001315 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1316 goto out;
William Lallemand9d5f5482012-11-07 16:12:57 +01001317 if (*(args[1]) == 0) {
1318 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1319 err_code |= ERR_ALERT | ERR_FATAL;
1320 goto out;
1321 }
William Lallemande3a7d992012-11-20 11:25:20 +01001322 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001323 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001324 else if (!strcmp(args[0], "maxcompcpuusage")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001325 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1326 goto out;
William Lallemand072a2bf2012-11-20 17:01:01 +01001327 if (*(args[1]) == 0) {
1328 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1329 err_code |= ERR_ALERT | ERR_FATAL;
1330 goto out;
1331 }
1332 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001333 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001334 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1335 err_code |= ERR_ALERT | ERR_FATAL;
1336 goto out;
1337 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001338 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001339
Willy Tarreaubaaee002006-06-26 02:48:02 +02001340 else if (!strcmp(args[0], "ulimit-n")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001341 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1342 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001343 if (global.rlimit_nofile != 0) {
1344 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001345 err_code |= ERR_ALERT;
1346 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001347 }
1348 if (*(args[1]) == 0) {
1349 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001350 err_code |= ERR_ALERT | ERR_FATAL;
1351 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001352 }
1353 global.rlimit_nofile = atol(args[1]);
1354 }
1355 else if (!strcmp(args[0], "chroot")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001356 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1357 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001358 if (global.chroot != NULL) {
1359 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001360 err_code |= ERR_ALERT;
1361 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001362 }
1363 if (*(args[1]) == 0) {
1364 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001365 err_code |= ERR_ALERT | ERR_FATAL;
1366 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001367 }
1368 global.chroot = strdup(args[1]);
1369 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001370 else if (!strcmp(args[0], "description")) {
1371 int i, len=0;
1372 char *d;
1373
1374 if (!*args[1]) {
1375 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1376 file, linenum, args[0]);
1377 err_code |= ERR_ALERT | ERR_FATAL;
1378 goto out;
1379 }
1380
Willy Tarreau348acfe2014-04-14 15:00:39 +02001381 for (i = 1; *args[i]; i++)
1382 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001383
1384 if (global.desc)
1385 free(global.desc);
1386
1387 global.desc = d = (char *)calloc(1, len);
1388
Willy Tarreau348acfe2014-04-14 15:00:39 +02001389 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1390 for (i = 2; *args[i]; i++)
1391 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001392 }
1393 else if (!strcmp(args[0], "node")) {
1394 int i;
1395 char c;
1396
William Lallemand1a748ae2015-05-19 16:37:23 +02001397 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1398 goto out;
1399
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001400 for (i=0; args[1][i]; i++) {
1401 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001402 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1403 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001404 break;
1405 }
1406
1407 if (!i || args[1][i]) {
1408 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1409 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1410 file, linenum, args[0]);
1411 err_code |= ERR_ALERT | ERR_FATAL;
1412 goto out;
1413 }
1414
1415 if (global.node)
1416 free(global.node);
1417
1418 global.node = strdup(args[1]);
1419 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001420 else if (!strcmp(args[0], "pidfile")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001421 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1422 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001423 if (global.pidfile != NULL) {
1424 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001425 err_code |= ERR_ALERT;
1426 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001427 }
1428 if (*(args[1]) == 0) {
1429 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001430 err_code |= ERR_ALERT | ERR_FATAL;
1431 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001432 }
1433 global.pidfile = strdup(args[1]);
1434 }
Emeric Bruned760922010-10-22 17:59:25 +02001435 else if (!strcmp(args[0], "unix-bind")) {
1436 int cur_arg = 1;
1437 while (*(args[cur_arg])) {
1438 if (!strcmp(args[cur_arg], "prefix")) {
1439 if (global.unix_bind.prefix != NULL) {
1440 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1441 err_code |= ERR_ALERT;
1442 cur_arg += 2;
1443 continue;
1444 }
1445
1446 if (*(args[cur_arg+1]) == 0) {
1447 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1448 err_code |= ERR_ALERT | ERR_FATAL;
1449 goto out;
1450 }
1451 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1452 cur_arg += 2;
1453 continue;
1454 }
1455
1456 if (!strcmp(args[cur_arg], "mode")) {
1457
1458 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1459 cur_arg += 2;
1460 continue;
1461 }
1462
1463 if (!strcmp(args[cur_arg], "uid")) {
1464
1465 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1466 cur_arg += 2;
1467 continue;
1468 }
1469
1470 if (!strcmp(args[cur_arg], "gid")) {
1471
1472 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1473 cur_arg += 2;
1474 continue;
1475 }
1476
1477 if (!strcmp(args[cur_arg], "user")) {
1478 struct passwd *user;
1479
1480 user = getpwnam(args[cur_arg + 1]);
1481 if (!user) {
1482 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1483 file, linenum, args[0], args[cur_arg + 1 ]);
1484 err_code |= ERR_ALERT | ERR_FATAL;
1485 goto out;
1486 }
1487
1488 global.unix_bind.ux.uid = user->pw_uid;
1489 cur_arg += 2;
1490 continue;
1491 }
1492
1493 if (!strcmp(args[cur_arg], "group")) {
1494 struct group *group;
1495
1496 group = getgrnam(args[cur_arg + 1]);
1497 if (!group) {
1498 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1499 file, linenum, args[0], args[cur_arg + 1 ]);
1500 err_code |= ERR_ALERT | ERR_FATAL;
1501 goto out;
1502 }
1503
1504 global.unix_bind.ux.gid = group->gr_gid;
1505 cur_arg += 2;
1506 continue;
1507 }
1508
Willy Tarreaub48f9582011-09-05 01:17:06 +02001509 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001510 file, linenum, args[0]);
1511 err_code |= ERR_ALERT | ERR_FATAL;
1512 goto out;
1513 }
1514 }
William Lallemand0f99e342011-10-12 17:50:54 +02001515 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1516 /* delete previous herited or defined syslog servers */
1517 struct logsrv *back;
1518 struct logsrv *tmp;
1519
1520 if (*(args[1]) != 0) {
1521 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1522 err_code |= ERR_ALERT | ERR_FATAL;
1523 goto out;
1524 }
1525
1526 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1527 LIST_DEL(&tmp->list);
1528 free(tmp);
1529 }
1530 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001531 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001532 struct sockaddr_storage *sk;
1533 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001534 struct logsrv *logsrv;
Willy Tarreau18324f52014-06-27 18:10:07 +02001535 int arg = 0;
1536 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001537
William Lallemand1a748ae2015-05-19 16:37:23 +02001538 if (alertif_too_many_args(8, file, linenum, args, &err_code)) /* does not strictly check optional arguments */
1539 goto out;
1540
Willy Tarreaubaaee002006-06-26 02:48:02 +02001541 if (*(args[1]) == 0 || *(args[2]) == 0) {
1542 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001543 err_code |= ERR_ALERT | ERR_FATAL;
1544 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001545 }
William Lallemand0f99e342011-10-12 17:50:54 +02001546
1547 logsrv = calloc(1, sizeof(struct logsrv));
1548
Willy Tarreau18324f52014-06-27 18:10:07 +02001549 /* just after the address, a length may be specified */
1550 if (strcmp(args[arg+2], "len") == 0) {
1551 len = atoi(args[arg+3]);
1552 if (len < 80 || len > 65535) {
1553 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1554 file, linenum, args[arg+3]);
1555 err_code |= ERR_ALERT | ERR_FATAL;
1556 goto out;
1557 }
1558 logsrv->maxlen = len;
1559
1560 /* skip these two args */
1561 arg += 2;
1562 }
1563 else
1564 logsrv->maxlen = MAX_SYSLOG_LEN;
1565
1566 if (logsrv->maxlen > global.max_syslog_len) {
1567 global.max_syslog_len = logsrv->maxlen;
1568 logline = realloc(logline, global.max_syslog_len + 1);
1569 }
1570
William Lallemand1a748ae2015-05-19 16:37:23 +02001571 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
1572 goto out;
1573
Willy Tarreau18324f52014-06-27 18:10:07 +02001574 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001575 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001576 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001577 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001578 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001579 }
1580
William Lallemand0f99e342011-10-12 17:50:54 +02001581 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02001582 if (*(args[arg+3])) {
1583 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001584 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001585 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001586 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001587 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001588 }
1589 }
1590
William Lallemand0f99e342011-10-12 17:50:54 +02001591 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02001592 if (*(args[arg+4])) {
1593 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001594 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001595 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001596 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001597 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001598 }
1599 }
1600
Willy Tarreau72b8c1f2015-09-08 15:50:19 +02001601 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001602 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001603 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001604 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001605 free(logsrv);
1606 goto out;
1607 }
1608 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001609
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001610 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001611 if (port1 != port2) {
1612 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1613 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001614 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001615 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001616 goto out;
1617 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001618
William Lallemand0f99e342011-10-12 17:50:54 +02001619 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001620 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001621 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001622 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001623
William Lallemand0f99e342011-10-12 17:50:54 +02001624 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001625 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001626 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1627 char *name;
1628 int len;
1629
1630 if (global.log_send_hostname != NULL) {
1631 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1632 err_code |= ERR_ALERT;
1633 goto out;
1634 }
1635
1636 if (*(args[1]))
1637 name = args[1];
1638 else
1639 name = hostname;
1640
1641 len = strlen(name);
1642
1643 /* We'll add a space after the name to respect the log format */
1644 free(global.log_send_hostname);
1645 global.log_send_hostname = malloc(len + 2);
1646 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1647 }
Kevinm48936af2010-12-22 16:08:21 +00001648 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
William Lallemand1a748ae2015-05-19 16:37:23 +02001649 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1650 goto out;
Kevinm48936af2010-12-22 16:08:21 +00001651 if (*(args[1]) == 0) {
1652 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1653 err_code |= ERR_ALERT | ERR_FATAL;
1654 goto out;
1655 }
1656 free(global.log_tag);
1657 global.log_tag = strdup(args[1]);
1658 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001659 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
William Lallemand1a748ae2015-05-19 16:37:23 +02001660 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1661 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001662 if (global.spread_checks != 0) {
1663 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001664 err_code |= ERR_ALERT;
1665 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001666 }
1667 if (*(args[1]) == 0) {
1668 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001669 err_code |= ERR_ALERT | ERR_FATAL;
1670 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001671 }
1672 global.spread_checks = atol(args[1]);
1673 if (global.spread_checks < 0 || global.spread_checks > 50) {
1674 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001675 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001676 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001677 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001678 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1679 const char *err;
1680 unsigned int val;
1681
William Lallemand1a748ae2015-05-19 16:37:23 +02001682 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1683 goto out;
Willy Tarreau1746eec2014-04-25 10:46:47 +02001684 if (*(args[1]) == 0) {
1685 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1686 err_code |= ERR_ALERT | ERR_FATAL;
1687 goto out;
1688 }
1689
1690 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1691 if (err) {
1692 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1693 err_code |= ERR_ALERT | ERR_FATAL;
1694 }
1695 global.max_spread_checks = val;
1696 if (global.max_spread_checks < 0) {
1697 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1698 err_code |= ERR_ALERT | ERR_FATAL;
1699 }
1700 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001701 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1702#ifdef USE_CPU_AFFINITY
1703 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001704 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001705 unsigned long cpus = 0;
1706
1707 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001708 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001709 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001710 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001711 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001712 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001713 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001714 proc = atol(args[1]);
1715 if (proc >= 1 && proc <= LONGBITS)
1716 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001717 }
1718
1719 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001720 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",
1721 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001722 err_code |= ERR_ALERT | ERR_FATAL;
1723 goto out;
1724 }
1725
1726 cur_arg = 2;
1727 while (*args[cur_arg]) {
1728 unsigned int low, high;
1729
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001730 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001731 char *dash = strchr(args[cur_arg], '-');
1732
1733 low = high = str2uic(args[cur_arg]);
1734 if (dash)
1735 high = str2uic(dash + 1);
1736
1737 if (high < low) {
1738 unsigned int swap = low;
1739 low = high;
1740 high = swap;
1741 }
1742
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001743 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001744 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001745 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001746 err_code |= ERR_ALERT | ERR_FATAL;
1747 goto out;
1748 }
1749
1750 while (low <= high)
1751 cpus |= 1UL << low++;
1752 }
1753 else {
1754 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1755 file, linenum, args[0], args[cur_arg]);
1756 err_code |= ERR_ALERT | ERR_FATAL;
1757 goto out;
1758 }
1759 cur_arg++;
1760 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001761 for (i = 0; i < LONGBITS; i++)
1762 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001763 global.cpu_map[i] = cpus;
1764#else
1765 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1766 err_code |= ERR_ALERT | ERR_FATAL;
1767 goto out;
1768#endif
1769 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001770 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001771 struct cfg_kw_list *kwl;
1772 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001773 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001774
1775 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1776 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1777 if (kwl->kw[index].section != CFG_GLOBAL)
1778 continue;
1779 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001780 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001781 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001782 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001783 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001784 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001785 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001786 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001787 err_code |= ERR_WARN;
1788 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001789 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001790 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001791 }
1792 }
1793 }
1794
Willy Tarreaubaaee002006-06-26 02:48:02 +02001795 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001796 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001797 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001798
Willy Tarreau058e9072009-07-20 09:30:05 +02001799 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001800 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001801 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001802}
1803
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001804void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001805{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001806 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001807 defproxy.mode = PR_MODE_TCP;
1808 defproxy.state = PR_STNEW;
1809 defproxy.maxconn = cfg_maxpconn;
1810 defproxy.conn_retries = CONN_RETRIES;
Joseph Lynch726ab712015-05-11 23:25:34 -07001811 defproxy.redispatch_after = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001812
Simon Horman66183002013-02-23 10:16:43 +09001813 defproxy.defsrv.check.inter = DEF_CHKINTR;
1814 defproxy.defsrv.check.fastinter = 0;
1815 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001816 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1817 defproxy.defsrv.agent.fastinter = 0;
1818 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001819 defproxy.defsrv.check.rise = DEF_RISETIME;
1820 defproxy.defsrv.check.fall = DEF_FALLTIME;
1821 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1822 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001823 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001824 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001825 defproxy.defsrv.maxqueue = 0;
1826 defproxy.defsrv.minconn = 0;
1827 defproxy.defsrv.maxconn = 0;
1828 defproxy.defsrv.slowstart = 0;
1829 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1830 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1831 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Simon Horman64e34162015-02-06 11:11:57 +09001832
1833 defproxy.email_alert.level = LOG_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001834}
1835
Willy Tarreauade5ec42010-01-28 19:33:49 +01001836
Willy Tarreau63af98d2014-05-18 08:11:41 +02001837/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1838 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1839 * ERR_FATAL in case of error.
1840 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001841static int create_cond_regex_rule(const char *file, int line,
1842 struct proxy *px, int dir, int action, int flags,
1843 const char *cmd, const char *reg, const char *repl,
1844 const char **cond_start)
1845{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001846 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001847 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001848 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001849 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001850 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001851 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001852 int cs;
1853 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001854
1855 if (px == &defproxy) {
1856 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001857 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001858 goto err;
1859 }
1860
1861 if (*reg == 0) {
1862 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001863 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001864 goto err;
1865 }
1866
1867 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001868 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001869
Willy Tarreau5321c422010-01-28 20:35:13 +01001870 if (cond_start &&
1871 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001872 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1873 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1874 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001875 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001876 goto err;
1877 }
1878 }
1879 else if (cond_start && **cond_start) {
1880 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1881 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001882 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001883 goto err;
1884 }
1885
Willy Tarreau63af98d2014-05-18 08:11:41 +02001886 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001887 (dir == SMP_OPT_DIR_REQ) ?
1888 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1889 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1890 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001891
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001892 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001893 if (!preg) {
1894 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001895 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001896 goto err;
1897 }
1898
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001899 cs = !(flags & REG_ICASE);
1900 cap = !(flags & REG_NOSUB);
1901 error = NULL;
1902 if (!regex_comp(reg, preg, cs, cap, &error)) {
1903 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1904 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001905 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001906 goto err;
1907 }
1908
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001909 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001910 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001911 if (repl && err) {
1912 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1913 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001914 ret_code |= ERR_ALERT | ERR_FATAL;
1915 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001916 }
1917
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001918 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001919 ret_code |= ERR_WARN;
1920
1921 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001922
Willy Tarreau63af98d2014-05-18 08:11:41 +02001923 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001924 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001925 err:
1926 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001927 free(errmsg);
1928 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001929}
1930
Willy Tarreaubaaee002006-06-26 02:48:02 +02001931/*
William Lallemand51097192015-04-14 16:35:22 +02001932 * Parse a line in a <listen>, <frontend> or <backend> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001933 * Returns the error code, 0 if OK, or any combination of :
1934 * - ERR_ABORT: must abort ASAP
1935 * - ERR_FATAL: we can continue parsing but not start the service
1936 * - ERR_WARN: a warning has been emitted
1937 * - ERR_ALERT: an alert has been emitted
1938 * Only the two first ones can stop processing, the two others are just
1939 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001940 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001941int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1942{
1943 static struct peers *curpeers = NULL;
1944 struct peer *newpeer = NULL;
1945 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001946 struct bind_conf *bind_conf;
1947 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001948 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001949 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001950
1951 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001952 if (!*args[1]) {
1953 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001954 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001955 goto out;
1956 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001957
William Lallemand6e62fb62015-04-28 16:55:23 +02001958 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1959 goto out;
1960
Emeric Brun32da3c42010-09-23 18:39:19 +02001961 err = invalid_char(args[1]);
1962 if (err) {
1963 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1964 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001965 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001966 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001967 }
1968
1969 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1970 /*
1971 * If there are two proxies with the same name only following
1972 * combinations are allowed:
1973 */
1974 if (strcmp(curpeers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02001975 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 +02001976 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02001977 err_code |= ERR_ALERT | ERR_FATAL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001978 }
1979 }
1980
1981 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1982 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1983 err_code |= ERR_ALERT | ERR_ABORT;
1984 goto out;
1985 }
1986
1987 curpeers->next = peers;
1988 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001989 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001990 curpeers->conf.line = linenum;
1991 curpeers->last_change = now.tv_sec;
1992 curpeers->id = strdup(args[1]);
Willy Tarreau77e4bd12015-05-01 20:02:17 +02001993 curpeers->state = PR_STNEW;
Emeric Brun32da3c42010-09-23 18:39:19 +02001994 }
1995 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001996 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001997 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001998 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001999
2000 if (!*args[2]) {
2001 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2002 file, linenum, args[0]);
2003 err_code |= ERR_ALERT | ERR_FATAL;
2004 goto out;
2005 }
2006
2007 err = invalid_char(args[1]);
2008 if (err) {
2009 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2010 file, linenum, *err, args[1]);
2011 err_code |= ERR_ALERT | ERR_FATAL;
2012 goto out;
2013 }
2014
2015 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
2016 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2017 err_code |= ERR_ALERT | ERR_ABORT;
2018 goto out;
2019 }
2020
2021 /* the peers are linked backwards first */
2022 curpeers->count++;
2023 newpeer->next = curpeers->remote;
2024 curpeers->remote = newpeer;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002025 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002026 newpeer->conf.line = linenum;
2027
2028 newpeer->last_change = now.tv_sec;
2029 newpeer->id = strdup(args[1]);
2030
Willy Tarreau72b8c1f2015-09-08 15:50:19 +02002031 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002032 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01002033 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002034 err_code |= ERR_ALERT | ERR_FATAL;
2035 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002036 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01002037
2038 proto = protocol_by_family(sk->ss_family);
2039 if (!proto || !proto->connect) {
2040 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2041 file, linenum, args[0], args[1]);
2042 err_code |= ERR_ALERT | ERR_FATAL;
2043 goto out;
2044 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002045
2046 if (port1 != port2) {
2047 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2048 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002049 err_code |= ERR_ALERT | ERR_FATAL;
2050 goto out;
2051 }
2052
Willy Tarreau2aa38802013-02-20 19:20:59 +01002053 if (!port1) {
2054 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2055 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002056 err_code |= ERR_ALERT | ERR_FATAL;
2057 goto out;
2058 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002059
Emeric Brun32da3c42010-09-23 18:39:19 +02002060 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002061 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002062 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02002063 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02002064
Emeric Brun32da3c42010-09-23 18:39:19 +02002065 if (strcmp(newpeer->id, localpeer) == 0) {
2066 /* Current is local peer, it define a frontend */
2067 newpeer->local = 1;
Emeric Brunb3971ab2015-05-12 18:49:09 +02002068 peers->local = newpeer;
Emeric Brun32da3c42010-09-23 18:39:19 +02002069
2070 if (!curpeers->peers_fe) {
2071 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
2072 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2073 err_code |= ERR_ALERT | ERR_ABORT;
2074 goto out;
2075 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002076
Willy Tarreau237250c2011-07-29 01:49:03 +02002077 init_new_proxy(curpeers->peers_fe);
2078 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02002079 curpeers->peers_fe->id = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002080 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
2081 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau91d96282015-03-13 15:47:26 +01002082 peers_setup_frontend(curpeers->peers_fe);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002083
2084 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
2085
Willy Tarreau902636f2013-03-10 19:44:48 +01002086 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
2087 if (errmsg && *errmsg) {
2088 indent_msg(&errmsg, 2);
2089 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002090 }
2091 else
2092 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
2093 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002094 err_code |= ERR_FATAL;
2095 goto out;
2096 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02002097
2098 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01002099 l->maxaccept = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002100 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
2101 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
Willy Tarreau9903f0e2015-04-04 18:50:31 +02002102 l->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02002103 l->handler = process_stream;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002104 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01002105 l->default_target = ((struct proxy *)curpeers->peers_fe)->default_target;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002106 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
2107 global.maxsock += l->maxconn;
2108 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002109 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01002110 else {
2111 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
2112 file, linenum, args[0], args[1],
2113 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
2114 err_code |= ERR_FATAL;
2115 goto out;
2116 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002117 }
2118 } /* neither "peer" nor "peers" */
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002119 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
2120 curpeers->state = PR_STSTOPPED;
2121 }
2122 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
2123 curpeers->state = PR_STNEW;
2124 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002125 else if (*args[0] != 0) {
2126 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2127 err_code |= ERR_ALERT | ERR_FATAL;
2128 goto out;
2129 }
2130
2131out:
Willy Tarreau902636f2013-03-10 19:44:48 +01002132 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02002133 return err_code;
2134}
2135
Baptiste Assmann325137d2015-04-13 23:40:55 +02002136/*
2137 * Parse a <resolvers> section.
2138 * Returns the error code, 0 if OK, or any combination of :
2139 * - ERR_ABORT: must abort ASAP
2140 * - ERR_FATAL: we can continue parsing but not start the service
2141 * - ERR_WARN: a warning has been emitted
2142 * - ERR_ALERT: an alert has been emitted
2143 * Only the two first ones can stop processing, the two others are just
2144 * indicators.
2145 */
2146int cfg_parse_resolvers(const char *file, int linenum, char **args, int kwm)
2147{
2148 static struct dns_resolvers *curr_resolvers = NULL;
2149 struct dns_nameserver *newnameserver = NULL;
2150 const char *err;
2151 int err_code = 0;
2152 char *errmsg = NULL;
2153
2154 if (strcmp(args[0], "resolvers") == 0) { /* new resolvers section */
2155 if (!*args[1]) {
2156 Alert("parsing [%s:%d] : missing name for resolvers section.\n", file, linenum);
2157 err_code |= ERR_ALERT | ERR_ABORT;
2158 goto out;
2159 }
2160
2161 err = invalid_char(args[1]);
2162 if (err) {
2163 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2164 file, linenum, *err, args[0], args[1]);
2165 err_code |= ERR_ALERT | ERR_ABORT;
2166 goto out;
2167 }
2168
2169 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
2170 /* Error if two resolvers owns the same name */
2171 if (strcmp(curr_resolvers->id, args[1]) == 0) {
2172 Alert("Parsing [%s:%d]: resolvers '%s' has same name as another resolvers (declared at %s:%d).\n",
2173 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2174 err_code |= ERR_ALERT | ERR_ABORT;
2175 }
2176 }
2177
2178 if ((curr_resolvers = (struct dns_resolvers *)calloc(1, sizeof(struct dns_resolvers))) == NULL) {
2179 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2180 err_code |= ERR_ALERT | ERR_ABORT;
2181 goto out;
2182 }
2183
2184 /* default values */
2185 LIST_ADDQ(&dns_resolvers, &curr_resolvers->list);
2186 curr_resolvers->conf.file = strdup(file);
2187 curr_resolvers->conf.line = linenum;
2188 curr_resolvers->id = strdup(args[1]);
2189 curr_resolvers->query_ids = EB_ROOT;
2190 /* default hold period for valid is 10s */
Baptiste Assmann4c5490a2015-07-14 21:42:49 +02002191 curr_resolvers->hold.valid = 10000;
2192 curr_resolvers->timeout.retry = 1000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002193 curr_resolvers->resolve_retries = 3;
2194 LIST_INIT(&curr_resolvers->nameserver_list);
2195 LIST_INIT(&curr_resolvers->curr_resolution);
2196 }
2197 else if (strcmp(args[0], "nameserver") == 0) { /* nameserver definition */
2198 struct sockaddr_storage *sk;
2199 int port1, port2;
2200 struct protocol *proto;
2201
2202 if (!*args[2]) {
2203 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2204 file, linenum, args[0]);
2205 err_code |= ERR_ALERT | ERR_FATAL;
2206 goto out;
2207 }
2208
2209 err = invalid_char(args[1]);
2210 if (err) {
2211 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2212 file, linenum, *err, args[1]);
2213 err_code |= ERR_ALERT | ERR_FATAL;
2214 goto out;
2215 }
2216
2217 if ((newnameserver = (struct dns_nameserver *)calloc(1, sizeof(struct dns_nameserver))) == NULL) {
2218 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2219 err_code |= ERR_ALERT | ERR_ABORT;
2220 goto out;
2221 }
2222
2223 /* the nameservers are linked backward first */
2224 LIST_ADDQ(&curr_resolvers->nameserver_list, &newnameserver->list);
2225 curr_resolvers->count_nameservers++;
2226 newnameserver->resolvers = curr_resolvers;
2227 newnameserver->conf.file = strdup(file);
2228 newnameserver->conf.line = linenum;
2229 newnameserver->id = strdup(args[1]);
2230
Willy Tarreau72b8c1f2015-09-08 15:50:19 +02002231 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002232 if (!sk) {
2233 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2234 err_code |= ERR_ALERT | ERR_FATAL;
2235 goto out;
2236 }
2237
2238 proto = protocol_by_family(sk->ss_family);
2239 if (!proto || !proto->connect) {
2240 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2241 file, linenum, args[0], args[1]);
2242 err_code |= ERR_ALERT | ERR_FATAL;
2243 goto out;
2244 }
2245
2246 if (port1 != port2) {
2247 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2248 file, linenum, args[0], args[1], args[2]);
2249 err_code |= ERR_ALERT | ERR_FATAL;
2250 goto out;
2251 }
2252
2253 newnameserver->addr = *sk;
2254 }
2255 else if (strcmp(args[0], "hold") == 0) { /* hold periods */
2256 const char *res;
2257 unsigned int time;
2258
2259 if (!*args[2]) {
2260 Alert("parsing [%s:%d] : '%s' expects an <event> and a <time> as arguments.\n",
2261 file, linenum, args[0]);
2262 Alert("<event> can be either 'valid', 'nx', 'refused', 'timeout', or 'other'\n");
2263 err_code |= ERR_ALERT | ERR_FATAL;
2264 goto out;
2265 }
2266 res = parse_time_err(args[2], &time, TIME_UNIT_MS);
2267 if (res) {
2268 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2269 file, linenum, *res, args[0]);
2270 err_code |= ERR_ALERT | ERR_FATAL;
2271 goto out;
2272 }
2273 if (strcmp(args[1], "valid") == 0)
2274 curr_resolvers->hold.valid = time;
2275 else {
2276 Alert("parsing [%s:%d] : '%s' unknown <event>: '%s', expects 'valid'\n",
2277 file, linenum, args[0], args[1]);
2278 err_code |= ERR_ALERT | ERR_FATAL;
2279 goto out;
2280 }
2281
2282 }
2283 else if (strcmp(args[0], "resolve_retries") == 0) {
2284 if (!*args[1]) {
2285 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2286 file, linenum, args[0]);
2287 err_code |= ERR_ALERT | ERR_FATAL;
2288 goto out;
2289 }
2290 curr_resolvers->resolve_retries = atoi(args[1]);
2291 }
2292 else if (strcmp(args[0], "timeout") == 0) {
2293 const char *res;
2294 unsigned int timeout_retry;
2295
2296 if (!*args[2]) {
2297 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments.\n",
2298 file, linenum, args[0]);
2299 err_code |= ERR_ALERT | ERR_FATAL;
2300 goto out;
2301 }
2302 res = parse_time_err(args[2], &timeout_retry, TIME_UNIT_MS);
2303 if (res) {
2304 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2305 file, linenum, *res, args[0]);
2306 err_code |= ERR_ALERT | ERR_FATAL;
2307 goto out;
2308 }
2309 curr_resolvers->timeout.retry = timeout_retry;
2310 } /* neither "nameserver" nor "resolvers" */
2311 else if (*args[0] != 0) {
2312 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2313 err_code |= ERR_ALERT | ERR_FATAL;
2314 goto out;
2315 }
2316
2317 out:
2318 free(errmsg);
2319 return err_code;
2320}
Simon Horman0d16a402015-01-30 11:22:58 +09002321
2322/*
William Lallemand51097192015-04-14 16:35:22 +02002323 * Parse a line in a <listen>, <frontend> or <backend> section.
Simon Horman0d16a402015-01-30 11:22:58 +09002324 * Returns the error code, 0 if OK, or any combination of :
2325 * - ERR_ABORT: must abort ASAP
2326 * - ERR_FATAL: we can continue parsing but not start the service
2327 * - ERR_WARN: a warning has been emitted
2328 * - ERR_ALERT: an alert has been emitted
2329 * Only the two first ones can stop processing, the two others are just
2330 * indicators.
2331 */
2332int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
2333{
2334 static struct mailers *curmailers = NULL;
2335 struct mailer *newmailer = NULL;
2336 const char *err;
2337 int err_code = 0;
2338 char *errmsg = NULL;
2339
2340 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
2341 if (!*args[1]) {
2342 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
2343 err_code |= ERR_ALERT | ERR_ABORT;
2344 goto out;
2345 }
2346
2347 err = invalid_char(args[1]);
2348 if (err) {
2349 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2350 file, linenum, *err, args[0], args[1]);
2351 err_code |= ERR_ALERT | ERR_ABORT;
2352 goto out;
2353 }
2354
2355 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
2356 /*
2357 * If there are two proxies with the same name only following
2358 * combinations are allowed:
2359 */
2360 if (strcmp(curmailers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002361 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 +09002362 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002363 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman0d16a402015-01-30 11:22:58 +09002364 }
2365 }
2366
2367 if ((curmailers = (struct mailers *)calloc(1, sizeof(struct mailers))) == NULL) {
2368 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2369 err_code |= ERR_ALERT | ERR_ABORT;
2370 goto out;
2371 }
2372
2373 curmailers->next = mailers;
2374 mailers = curmailers;
2375 curmailers->conf.file = strdup(file);
2376 curmailers->conf.line = linenum;
2377 curmailers->id = strdup(args[1]);
2378 }
2379 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
2380 struct sockaddr_storage *sk;
2381 int port1, port2;
2382 struct protocol *proto;
2383
2384 if (!*args[2]) {
2385 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2386 file, linenum, args[0]);
2387 err_code |= ERR_ALERT | ERR_FATAL;
2388 goto out;
2389 }
2390
2391 err = invalid_char(args[1]);
2392 if (err) {
2393 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2394 file, linenum, *err, args[1]);
2395 err_code |= ERR_ALERT | ERR_FATAL;
2396 goto out;
2397 }
2398
2399 if ((newmailer = (struct mailer *)calloc(1, sizeof(struct mailer))) == NULL) {
2400 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2401 err_code |= ERR_ALERT | ERR_ABORT;
2402 goto out;
2403 }
2404
2405 /* the mailers are linked backwards first */
2406 curmailers->count++;
2407 newmailer->next = curmailers->mailer_list;
2408 curmailers->mailer_list = newmailer;
2409 newmailer->mailers = curmailers;
2410 newmailer->conf.file = strdup(file);
2411 newmailer->conf.line = linenum;
2412
2413 newmailer->id = strdup(args[1]);
2414
Willy Tarreau72b8c1f2015-09-08 15:50:19 +02002415 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL);
Simon Horman0d16a402015-01-30 11:22:58 +09002416 if (!sk) {
2417 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2418 err_code |= ERR_ALERT | ERR_FATAL;
2419 goto out;
2420 }
2421
2422 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002423 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2424 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002425 file, linenum, args[0], args[1]);
2426 err_code |= ERR_ALERT | ERR_FATAL;
2427 goto out;
2428 }
2429
2430 if (port1 != port2) {
2431 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2432 file, linenum, args[0], args[1], args[2]);
2433 err_code |= ERR_ALERT | ERR_FATAL;
2434 goto out;
2435 }
2436
2437 if (!port1) {
2438 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2439 file, linenum, args[0], args[1], args[2]);
2440 err_code |= ERR_ALERT | ERR_FATAL;
2441 goto out;
2442 }
2443
2444 newmailer->addr = *sk;
2445 newmailer->proto = proto;
2446 newmailer->xprt = &raw_sock;
2447 newmailer->sock_init_arg = NULL;
2448 } /* neither "mailer" nor "mailers" */
2449 else if (*args[0] != 0) {
2450 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2451 err_code |= ERR_ALERT | ERR_FATAL;
2452 goto out;
2453 }
2454
2455out:
2456 free(errmsg);
2457 return err_code;
2458}
2459
Simon Horman9dc49962015-01-30 11:22:59 +09002460static void free_email_alert(struct proxy *p)
2461{
2462 free(p->email_alert.mailers.name);
2463 p->email_alert.mailers.name = NULL;
2464 free(p->email_alert.from);
2465 p->email_alert.from = NULL;
2466 free(p->email_alert.to);
2467 p->email_alert.to = NULL;
2468 free(p->email_alert.myhostname);
2469 p->email_alert.myhostname = NULL;
2470}
2471
Willy Tarreau3842f002009-06-14 11:39:52 +02002472int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002473{
2474 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002475 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002476 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002477 int rc;
2478 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002479 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002480 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002481 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002482 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002483 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002484
Willy Tarreau977b8e42006-12-29 14:19:17 +01002485 if (!strcmp(args[0], "listen"))
2486 rc = PR_CAP_LISTEN;
2487 else if (!strcmp(args[0], "frontend"))
2488 rc = PR_CAP_FE | PR_CAP_RS;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02002489 else if (!strcmp(args[0], "backend"))
Willy Tarreau977b8e42006-12-29 14:19:17 +01002490 rc = PR_CAP_BE | PR_CAP_RS;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002491 else
2492 rc = PR_CAP_NONE;
2493
2494 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002495 if (!*args[1]) {
2496 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
2497 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
2498 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002499 err_code |= ERR_ALERT | ERR_ABORT;
2500 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002501 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002502
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002503 err = invalid_char(args[1]);
2504 if (err) {
2505 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2506 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002507 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002508 }
2509
Willy Tarreau8f50b682015-05-26 11:45:02 +02002510 curproxy = (rc & PR_CAP_FE) ? proxy_fe_by_name(args[1]) : proxy_be_by_name(args[1]);
2511 if (curproxy) {
2512 Alert("Parsing [%s:%d]: %s '%s' has the same name as %s '%s' declared at %s:%d.\n",
2513 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2514 curproxy->id, curproxy->conf.file, curproxy->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002515 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002516 }
2517
Willy Tarreaubaaee002006-06-26 02:48:02 +02002518 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
2519 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002520 err_code |= ERR_ALERT | ERR_ABORT;
2521 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002522 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002523
Willy Tarreau97cb7802010-01-03 20:23:58 +01002524 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002525 curproxy->next = proxy;
2526 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002527 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2528 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002529 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002530 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002531 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002532 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002533
William Lallemand6e62fb62015-04-28 16:55:23 +02002534 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2535 if (curproxy->cap & PR_CAP_FE)
2536 Alert("parsing [%s:%d] : please use the 'bind' keyword for listening addresses.\n", file, linenum);
2537 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002538 }
2539
2540 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002541 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002542 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002543
Willy Tarreaubaaee002006-06-26 02:48:02 +02002544 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002545 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002546 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002547 curproxy->no_options = defproxy.no_options;
2548 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002549 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002550 curproxy->except_net = defproxy.except_net;
2551 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002552 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002553 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002554
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002555 if (defproxy.fwdfor_hdr_len) {
2556 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2557 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2558 }
2559
Willy Tarreaub86db342009-11-30 11:50:16 +01002560 if (defproxy.orgto_hdr_len) {
2561 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2562 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2563 }
2564
Mark Lamourinec2247f02012-01-04 13:02:01 -05002565 if (defproxy.server_id_hdr_len) {
2566 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2567 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2568 }
2569
Willy Tarreau977b8e42006-12-29 14:19:17 +01002570 if (curproxy->cap & PR_CAP_FE) {
2571 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002572 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002573 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002574
2575 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002576 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2577 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002578
2579 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2580 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002581
Willy Tarreau977b8e42006-12-29 14:19:17 +01002582 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002583 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002584 curproxy->fullconn = defproxy.fullconn;
2585 curproxy->conn_retries = defproxy.conn_retries;
Joseph Lynch726ab712015-05-11 23:25:34 -07002586 curproxy->redispatch_after = defproxy.redispatch_after;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002587 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002588
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002589 if (defproxy.check_req) {
2590 curproxy->check_req = calloc(1, defproxy.check_len);
2591 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2592 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002593 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002594
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002595 if (defproxy.expect_str) {
2596 curproxy->expect_str = strdup(defproxy.expect_str);
2597 if (defproxy.expect_regex) {
2598 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002599 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2600 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002601 }
2602 }
2603
Willy Tarreau67402132012-05-31 20:40:20 +02002604 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002605 if (defproxy.cookie_name)
2606 curproxy->cookie_name = strdup(defproxy.cookie_name);
2607 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002608 if (defproxy.cookie_domain)
2609 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002610
Willy Tarreau31936852010-10-06 16:59:56 +02002611 if (defproxy.cookie_maxidle)
2612 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2613
2614 if (defproxy.cookie_maxlife)
2615 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2616
Emeric Brun647caf12009-06-30 17:57:00 +02002617 if (defproxy.rdp_cookie_name)
2618 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2619 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2620
Willy Tarreau01732802007-11-01 22:48:15 +01002621 if (defproxy.url_param_name)
2622 curproxy->url_param_name = strdup(defproxy.url_param_name);
2623 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002624
Benoitaffb4812009-03-25 13:02:10 +01002625 if (defproxy.hh_name)
2626 curproxy->hh_name = strdup(defproxy.hh_name);
2627 curproxy->hh_len = defproxy.hh_len;
2628 curproxy->hh_match_domain = defproxy.hh_match_domain;
2629
Willy Tarreauef9a3602012-12-08 22:29:20 +01002630 if (defproxy.conn_src.iface_name)
2631 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2632 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002633 curproxy->conn_src.opts = defproxy.conn_src.opts;
Willy Tarreau29fbe512015-08-20 19:35:14 +02002634#if defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002635 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002636#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01002637 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002638
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002639 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002640 if (defproxy.capture_name)
2641 curproxy->capture_name = strdup(defproxy.capture_name);
2642 curproxy->capture_namelen = defproxy.capture_namelen;
2643 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002644 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002645
Willy Tarreau977b8e42006-12-29 14:19:17 +01002646 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002647 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002648 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002649 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002650 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002651 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002652 curproxy->mon_net = defproxy.mon_net;
2653 curproxy->mon_mask = defproxy.mon_mask;
2654 if (defproxy.monitor_uri)
2655 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2656 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002657 if (defproxy.defbe.name)
2658 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002659
2660 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002661 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2662 if (curproxy->conf.logformat_string &&
2663 curproxy->conf.logformat_string != default_http_log_format &&
2664 curproxy->conf.logformat_string != default_tcp_log_format &&
2665 curproxy->conf.logformat_string != clf_http_log_format)
2666 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2667
2668 if (defproxy.conf.lfs_file) {
2669 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2670 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2671 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002672 }
2673
2674 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002675 curproxy->timeout.connect = defproxy.timeout.connect;
2676 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002677 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002678 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002679 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002680 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002681 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002682 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002683 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002684 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002685 }
2686
Willy Tarreaubaaee002006-06-26 02:48:02 +02002687 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002688 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002689
2690 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002691 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002692 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002693 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002694 LIST_INIT(&node->list);
2695 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2696 }
2697
Willy Tarreau62a61232013-04-12 18:13:46 +02002698 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2699 if (curproxy->conf.uniqueid_format_string)
2700 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2701
Willy Tarreau094af4e2015-01-07 15:03:42 +01002702 if (defproxy.log_tag)
2703 curproxy->log_tag = strdup(defproxy.log_tag);
2704
Willy Tarreau62a61232013-04-12 18:13:46 +02002705 if (defproxy.conf.uif_file) {
2706 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2707 curproxy->conf.uif_line = defproxy.conf.uif_line;
2708 }
William Lallemanda73203e2012-03-12 12:48:57 +01002709
2710 /* copy default header unique id */
2711 if (defproxy.header_unique_id)
2712 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2713
William Lallemand82fe75c2012-10-23 10:25:10 +02002714 /* default compression options */
2715 if (defproxy.comp != NULL) {
2716 curproxy->comp = calloc(1, sizeof(struct comp));
2717 curproxy->comp->algos = defproxy.comp->algos;
2718 curproxy->comp->types = defproxy.comp->types;
2719 }
2720
Willy Tarreaubaaee002006-06-26 02:48:02 +02002721 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002722 curproxy->conf.used_listener_id = EB_ROOT;
2723 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002724
Simon Horman98637e52014-06-20 12:30:16 +09002725 if (defproxy.check_path)
2726 curproxy->check_path = strdup(defproxy.check_path);
2727 if (defproxy.check_command)
2728 curproxy->check_command = strdup(defproxy.check_command);
2729
Simon Horman9dc49962015-01-30 11:22:59 +09002730 if (defproxy.email_alert.mailers.name)
2731 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2732 if (defproxy.email_alert.from)
2733 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2734 if (defproxy.email_alert.to)
2735 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2736 if (defproxy.email_alert.myhostname)
2737 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09002738 curproxy->email_alert.level = defproxy.email_alert.level;
Simon Horman9dc49962015-01-30 11:22:59 +09002739
Willy Tarreau93893792009-07-23 13:19:11 +02002740 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002741 }
2742 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2743 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002744 /* FIXME-20070101: we should do this too at the end of the
2745 * config parsing to free all default values.
2746 */
William Lallemand6e62fb62015-04-28 16:55:23 +02002747 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2748 err_code |= ERR_ABORT;
2749 goto out;
2750 }
2751
Willy Tarreaua534fea2008-08-03 12:19:50 +02002752 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002753 free(defproxy.check_command);
2754 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002755 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002756 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002757 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002758 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002759 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002760 free(defproxy.capture_name);
2761 free(defproxy.monitor_uri);
2762 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002763 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002764 free(defproxy.fwdfor_hdr_name);
2765 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002766 free(defproxy.orgto_hdr_name);
2767 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002768 free(defproxy.server_id_hdr_name);
2769 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002770 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002771 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002772 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002773 free(defproxy.expect_regex);
2774 defproxy.expect_regex = NULL;
2775 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002776
Willy Tarreau62a61232013-04-12 18:13:46 +02002777 if (defproxy.conf.logformat_string != default_http_log_format &&
2778 defproxy.conf.logformat_string != default_tcp_log_format &&
2779 defproxy.conf.logformat_string != clf_http_log_format)
2780 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002781
Willy Tarreau62a61232013-04-12 18:13:46 +02002782 free(defproxy.conf.uniqueid_format_string);
2783 free(defproxy.conf.lfs_file);
2784 free(defproxy.conf.uif_file);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002785 free(defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09002786 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02002787
Willy Tarreaua534fea2008-08-03 12:19:50 +02002788 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002789 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002790
Willy Tarreaubaaee002006-06-26 02:48:02 +02002791 /* we cannot free uri_auth because it might already be used */
2792 init_default_instance();
2793 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002794 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2795 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002796 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002797 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002798 }
2799 else if (curproxy == NULL) {
2800 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002801 err_code |= ERR_ALERT | ERR_FATAL;
2802 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002803 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002804
2805 /* update the current file and line being parsed */
2806 curproxy->conf.args.file = curproxy->conf.file;
2807 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002808
2809 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002810 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2811 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2812 if (err_code & ERR_FATAL)
2813 goto out;
2814 }
2815 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002816 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002817 int cur_arg;
2818
Willy Tarreaubaaee002006-06-26 02:48:02 +02002819 if (curproxy == &defproxy) {
2820 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002821 err_code |= ERR_ALERT | ERR_FATAL;
2822 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002823 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002824 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002825 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002826
Willy Tarreau24709282013-03-10 21:32:12 +01002827 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002828 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002829 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002830 err_code |= ERR_ALERT | ERR_FATAL;
2831 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002832 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002833
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002834 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002835
2836 /* use default settings for unix sockets */
2837 bind_conf->ux.uid = global.unix_bind.ux.uid;
2838 bind_conf->ux.gid = global.unix_bind.ux.gid;
2839 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002840
2841 /* NOTE: the following line might create several listeners if there
2842 * are comma-separated IPs or port ranges. So all further processing
2843 * will have to be applied to all listeners created after last_listen.
2844 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002845 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2846 if (errmsg && *errmsg) {
2847 indent_msg(&errmsg, 2);
2848 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002849 }
2850 else
2851 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2852 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002853 err_code |= ERR_ALERT | ERR_FATAL;
2854 goto out;
2855 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002856
Willy Tarreau4348fad2012-09-20 16:48:07 +02002857 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2858 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002859 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002860 }
2861
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002862 cur_arg = 2;
2863 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002864 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002865 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002866 char *err;
2867
Willy Tarreau26982662012-09-12 23:17:10 +02002868 kw = bind_find_kw(args[cur_arg]);
2869 if (kw) {
2870 char *err = NULL;
2871 int code;
2872
2873 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002874 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2875 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002876 cur_arg += 1 + kw->skip ;
2877 err_code |= ERR_ALERT | ERR_FATAL;
2878 goto out;
2879 }
2880
Willy Tarreau4348fad2012-09-20 16:48:07 +02002881 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002882 err_code |= code;
2883
2884 if (code) {
2885 if (err && *err) {
2886 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002887 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002888 }
2889 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002890 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2891 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002892 if (code & ERR_FATAL) {
2893 free(err);
2894 cur_arg += 1 + kw->skip;
2895 goto out;
2896 }
2897 }
2898 free(err);
2899 cur_arg += 1 + kw->skip;
2900 continue;
2901 }
2902
Willy Tarreau8638f482012-09-18 18:01:17 +02002903 err = NULL;
2904 if (!bind_dumped) {
2905 bind_dump_kws(&err);
2906 indent_msg(&err, 4);
2907 bind_dumped = 1;
2908 }
2909
2910 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2911 file, linenum, args[0], args[1], args[cur_arg],
2912 err ? " Registered keywords :" : "", err ? err : "");
2913 free(err);
2914
Willy Tarreau93893792009-07-23 13:19:11 +02002915 err_code |= ERR_ALERT | ERR_FATAL;
2916 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002917 }
Willy Tarreau93893792009-07-23 13:19:11 +02002918 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002919 }
2920 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002921 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002922 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2923 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002924 err_code |= ERR_ALERT | ERR_FATAL;
2925 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002926 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002927 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002928 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002929
Willy Tarreaubaaee002006-06-26 02:48:02 +02002930 /* flush useless bits */
2931 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002932 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002933 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002934 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002935 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002936 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002937
William Lallemanddf1425a2015-04-28 20:17:49 +02002938 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2939 goto out;
2940
Willy Tarreau1c47f852006-07-09 08:22:27 +02002941 if (!*args[1]) {
2942 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2943 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002944 err_code |= ERR_ALERT | ERR_FATAL;
2945 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002946 }
2947
Willy Tarreaua534fea2008-08-03 12:19:50 +02002948 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002949 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002950 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002951 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002952 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2953
Willy Tarreau93893792009-07-23 13:19:11 +02002954 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002955 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002956 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
William Lallemanddf1425a2015-04-28 20:17:49 +02002957 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2958 goto out;
2959
Willy Tarreaubaaee002006-06-26 02:48:02 +02002960 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2961 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2962 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2963 else {
2964 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002965 err_code |= ERR_ALERT | ERR_FATAL;
2966 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002967 }
2968 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002969 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002970 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002971
2972 if (curproxy == &defproxy) {
2973 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2974 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002975 err_code |= ERR_ALERT | ERR_FATAL;
2976 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002977 }
2978
William Lallemanddf1425a2015-04-28 20:17:49 +02002979 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2980 goto out;
2981
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002982 if (!*args[1]) {
2983 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2984 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002985 err_code |= ERR_ALERT | ERR_FATAL;
2986 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002987 }
2988
2989 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002990 curproxy->conf.id.key = curproxy->uuid;
Willy Tarreau0d1fdf72015-05-27 16:44:02 +02002991 curproxy->options |= PR_O_FORCED_ID;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002992
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002993 if (curproxy->uuid <= 0) {
2994 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002995 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002996 err_code |= ERR_ALERT | ERR_FATAL;
2997 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002998 }
2999
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003000 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
3001 if (node) {
3002 struct proxy *target = container_of(node, struct proxy, conf.id);
3003 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
3004 file, linenum, proxy_type_str(curproxy), curproxy->id,
3005 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
3006 err_code |= ERR_ALERT | ERR_FATAL;
3007 goto out;
3008 }
3009 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003010 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003011 else if (!strcmp(args[0], "description")) {
3012 int i, len=0;
3013 char *d;
3014
Cyril Bonté99ed3272010-01-24 23:29:44 +01003015 if (curproxy == &defproxy) {
3016 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3017 file, linenum, args[0]);
3018 err_code |= ERR_ALERT | ERR_FATAL;
3019 goto out;
3020 }
3021
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003022 if (!*args[1]) {
3023 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
3024 file, linenum, args[0]);
3025 return -1;
3026 }
3027
Willy Tarreau348acfe2014-04-14 15:00:39 +02003028 for (i = 1; *args[i]; i++)
3029 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003030
3031 d = (char *)calloc(1, len);
3032 curproxy->desc = d;
3033
Willy Tarreau348acfe2014-04-14 15:00:39 +02003034 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
3035 for (i = 2; *args[i]; i++)
3036 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003037
3038 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003039 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
William Lallemanddf1425a2015-04-28 20:17:49 +02003040 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3041 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003042 curproxy->state = PR_STSTOPPED;
3043 }
3044 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
William Lallemanddf1425a2015-04-28 20:17:49 +02003045 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3046 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003047 curproxy->state = PR_STNEW;
3048 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003049 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
3050 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003051 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003052
3053 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003054 unsigned int low, high;
3055
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003056 if (strcmp(args[cur_arg], "all") == 0) {
3057 set = 0;
3058 break;
3059 }
3060 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003061 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003062 }
3063 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003064 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003065 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01003066 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003067 char *dash = strchr(args[cur_arg], '-');
3068
3069 low = high = str2uic(args[cur_arg]);
3070 if (dash)
3071 high = str2uic(dash + 1);
3072
3073 if (high < low) {
3074 unsigned int swap = low;
3075 low = high;
3076 high = swap;
3077 }
3078
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003079 if (low < 1 || high > LONGBITS) {
3080 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
3081 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02003082 err_code |= ERR_ALERT | ERR_FATAL;
3083 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003084 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01003085 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003086 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003087 }
3088 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003089 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
3090 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003091 err_code |= ERR_ALERT | ERR_FATAL;
3092 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003093 }
3094 cur_arg++;
3095 }
3096 curproxy->bind_proc = set;
3097 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003098 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02003099 if (curproxy == &defproxy) {
3100 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003101 err_code |= ERR_ALERT | ERR_FATAL;
3102 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003103 }
3104
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003105 err = invalid_char(args[1]);
3106 if (err) {
3107 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
3108 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003109 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003110 }
3111
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01003112 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003113 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
3114 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003115 err_code |= ERR_ALERT | ERR_FATAL;
3116 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003117 }
3118 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003119 else if (!strcmp(args[0], "cookie")) { /* cookie name */
3120 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003121
Willy Tarreau977b8e42006-12-29 14:19:17 +01003122 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003123 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003124
Willy Tarreaubaaee002006-06-26 02:48:02 +02003125 if (*(args[1]) == 0) {
3126 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
3127 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003128 err_code |= ERR_ALERT | ERR_FATAL;
3129 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003130 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003131
Willy Tarreau67402132012-05-31 20:40:20 +02003132 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003133 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01003134 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003135 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003136 curproxy->cookie_name = strdup(args[1]);
3137 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003138
Willy Tarreaubaaee002006-06-26 02:48:02 +02003139 cur_arg = 2;
3140 while (*(args[cur_arg])) {
3141 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003142 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003143 }
3144 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003145 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003146 }
3147 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003148 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003149 }
3150 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003151 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003152 }
3153 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003154 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003155 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003156 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003157 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003158 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003159 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003160 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003161 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02003162 else if (!strcmp(args[cur_arg], "httponly")) {
3163 curproxy->ck_opts |= PR_CK_HTTPONLY;
3164 }
3165 else if (!strcmp(args[cur_arg], "secure")) {
3166 curproxy->ck_opts |= PR_CK_SECURE;
3167 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003168 else if (!strcmp(args[cur_arg], "domain")) {
3169 if (!*args[cur_arg + 1]) {
3170 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
3171 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003172 err_code |= ERR_ALERT | ERR_FATAL;
3173 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003174 }
3175
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003176 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003177 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003178 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
3179 " dots nor does not start with a dot."
3180 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003181 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003182 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003183 }
3184
3185 err = invalid_domainchar(args[cur_arg + 1]);
3186 if (err) {
3187 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
3188 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003189 err_code |= ERR_ALERT | ERR_FATAL;
3190 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003191 }
3192
Willy Tarreau68a897b2009-12-03 23:28:34 +01003193 if (!curproxy->cookie_domain) {
3194 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
3195 } else {
3196 /* one domain was already specified, add another one by
3197 * building the string which will be returned along with
3198 * the cookie.
3199 */
3200 char *new_ptr;
3201 int new_len = strlen(curproxy->cookie_domain) +
3202 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
3203 new_ptr = malloc(new_len);
3204 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
3205 free(curproxy->cookie_domain);
3206 curproxy->cookie_domain = new_ptr;
3207 }
Willy Tarreau31936852010-10-06 16:59:56 +02003208 cur_arg++;
3209 }
3210 else if (!strcmp(args[cur_arg], "maxidle")) {
3211 unsigned int maxidle;
3212 const char *res;
3213
3214 if (!*args[cur_arg + 1]) {
3215 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
3216 file, linenum, args[cur_arg]);
3217 err_code |= ERR_ALERT | ERR_FATAL;
3218 goto out;
3219 }
3220
3221 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
3222 if (res) {
3223 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3224 file, linenum, *res, args[cur_arg]);
3225 err_code |= ERR_ALERT | ERR_FATAL;
3226 goto out;
3227 }
3228 curproxy->cookie_maxidle = maxidle;
3229 cur_arg++;
3230 }
3231 else if (!strcmp(args[cur_arg], "maxlife")) {
3232 unsigned int maxlife;
3233 const char *res;
3234
3235 if (!*args[cur_arg + 1]) {
3236 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
3237 file, linenum, args[cur_arg]);
3238 err_code |= ERR_ALERT | ERR_FATAL;
3239 goto out;
3240 }
3241
3242 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
3243 if (res) {
3244 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3245 file, linenum, *res, args[cur_arg]);
3246 err_code |= ERR_ALERT | ERR_FATAL;
3247 goto out;
3248 }
3249 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003250 cur_arg++;
3251 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003252 else {
Willy Tarreau31936852010-10-06 16:59:56 +02003253 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 +02003254 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003255 err_code |= ERR_ALERT | ERR_FATAL;
3256 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003257 }
3258 cur_arg++;
3259 }
Willy Tarreau67402132012-05-31 20:40:20 +02003260 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003261 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
3262 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003263 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003264 }
3265
Willy Tarreau67402132012-05-31 20:40:20 +02003266 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003267 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
3268 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003269 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003270 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003271
Willy Tarreau67402132012-05-31 20:40:20 +02003272 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003273 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
3274 file, linenum);
3275 err_code |= ERR_ALERT | ERR_FATAL;
3276 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003277 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09003278 else if (!strcmp(args[0], "email-alert")) {
3279 if (*(args[1]) == 0) {
3280 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3281 file, linenum, args[0]);
3282 err_code |= ERR_ALERT | ERR_FATAL;
3283 goto out;
3284 }
3285
3286 if (!strcmp(args[1], "from")) {
3287 if (*(args[1]) == 0) {
3288 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3289 file, linenum, args[1]);
3290 err_code |= ERR_ALERT | ERR_FATAL;
3291 goto out;
3292 }
3293 free(curproxy->email_alert.from);
3294 curproxy->email_alert.from = strdup(args[2]);
3295 }
3296 else if (!strcmp(args[1], "mailers")) {
3297 if (*(args[1]) == 0) {
3298 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3299 file, linenum, args[1]);
3300 err_code |= ERR_ALERT | ERR_FATAL;
3301 goto out;
3302 }
3303 free(curproxy->email_alert.mailers.name);
3304 curproxy->email_alert.mailers.name = strdup(args[2]);
3305 }
3306 else if (!strcmp(args[1], "myhostname")) {
3307 if (*(args[1]) == 0) {
3308 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3309 file, linenum, args[1]);
3310 err_code |= ERR_ALERT | ERR_FATAL;
3311 goto out;
3312 }
3313 free(curproxy->email_alert.myhostname);
3314 curproxy->email_alert.myhostname = strdup(args[2]);
3315 }
Simon Horman64e34162015-02-06 11:11:57 +09003316 else if (!strcmp(args[1], "level")) {
3317 curproxy->email_alert.level = get_log_level(args[2]);
3318 if (curproxy->email_alert.level < 0) {
3319 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
3320 file, linenum, args[1], args[2]);
3321 err_code |= ERR_ALERT | ERR_FATAL;
3322 goto out;
3323 }
3324 }
Simon Horman9dc49962015-01-30 11:22:59 +09003325 else if (!strcmp(args[1], "to")) {
3326 if (*(args[1]) == 0) {
3327 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3328 file, linenum, args[1]);
3329 err_code |= ERR_ALERT | ERR_FATAL;
3330 goto out;
3331 }
3332 free(curproxy->email_alert.to);
3333 curproxy->email_alert.to = strdup(args[2]);
3334 }
3335 else {
3336 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
3337 file, linenum, args[1]);
3338 err_code |= ERR_ALERT | ERR_FATAL;
3339 goto out;
3340 }
Simon Horman64e34162015-02-06 11:11:57 +09003341 /* Indicate that the email_alert is at least partially configured */
3342 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09003343 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09003344 else if (!strcmp(args[0], "external-check")) {
3345 if (*(args[1]) == 0) {
3346 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3347 file, linenum, args[0]);
3348 err_code |= ERR_ALERT | ERR_FATAL;
3349 goto out;
3350 }
3351
3352 if (!strcmp(args[1], "command")) {
William Lallemanddf1425a2015-04-28 20:17:49 +02003353 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3354 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09003355 if (*(args[1]) == 0) {
3356 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3357 file, linenum, args[1]);
3358 err_code |= ERR_ALERT | ERR_FATAL;
3359 goto out;
3360 }
3361 free(curproxy->check_command);
3362 curproxy->check_command = strdup(args[2]);
3363 }
3364 else if (!strcmp(args[1], "path")) {
William Lallemanddf1425a2015-04-28 20:17:49 +02003365 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3366 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09003367 if (*(args[1]) == 0) {
3368 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3369 file, linenum, args[1]);
3370 err_code |= ERR_ALERT | ERR_FATAL;
3371 goto out;
3372 }
3373 free(curproxy->check_path);
3374 curproxy->check_path = strdup(args[2]);
3375 }
3376 else {
3377 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
3378 file, linenum, args[1]);
3379 err_code |= ERR_ALERT | ERR_FATAL;
3380 goto out;
3381 }
3382 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02003383 else if (!strcmp(args[0], "persist")) { /* persist */
3384 if (*(args[1]) == 0) {
3385 Alert("parsing [%s:%d] : missing persist method.\n",
3386 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003387 err_code |= ERR_ALERT | ERR_FATAL;
3388 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003389 }
3390
3391 if (!strncmp(args[1], "rdp-cookie", 10)) {
3392 curproxy->options2 |= PR_O2_RDPC_PRST;
3393
Emeric Brunb982a3d2010-01-04 15:45:53 +01003394 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003395 const char *beg, *end;
3396
3397 beg = args[1] + 11;
3398 end = strchr(beg, ')');
3399
William Lallemanddf1425a2015-04-28 20:17:49 +02003400 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3401 goto out;
3402
Emeric Brun647caf12009-06-30 17:57:00 +02003403 if (!end || end == beg) {
3404 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3405 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003406 err_code |= ERR_ALERT | ERR_FATAL;
3407 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003408 }
3409
3410 free(curproxy->rdp_cookie_name);
3411 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3412 curproxy->rdp_cookie_len = end-beg;
3413 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003414 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003415 free(curproxy->rdp_cookie_name);
3416 curproxy->rdp_cookie_name = strdup("msts");
3417 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3418 }
3419 else { /* syntax */
3420 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3421 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003422 err_code |= ERR_ALERT | ERR_FATAL;
3423 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003424 }
3425 }
3426 else {
3427 Alert("parsing [%s:%d] : unknown persist method.\n",
3428 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003429 err_code |= ERR_ALERT | ERR_FATAL;
3430 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003431 }
3432 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003433 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreau6db62c52015-08-10 19:04:29 +02003434 Alert("parsing [%s:%d] : '%s' is not supported anymore, please check the documentation.\n", file, linenum, args[0]);
3435 err_code |= ERR_ALERT | ERR_FATAL;
3436 goto out;
3437 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003438 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003439 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003440 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003441
Willy Tarreaubaaee002006-06-26 02:48:02 +02003442 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003443 if (curproxy == &defproxy) {
3444 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3445 err_code |= ERR_ALERT | ERR_FATAL;
3446 goto out;
3447 }
3448
William Lallemand1a748ae2015-05-19 16:37:23 +02003449 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3450 goto out;
3451
Willy Tarreaubaaee002006-06-26 02:48:02 +02003452 if (*(args[4]) == 0) {
3453 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3454 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003455 err_code |= ERR_ALERT | ERR_FATAL;
3456 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003457 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003458 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003459 curproxy->capture_name = strdup(args[2]);
3460 curproxy->capture_namelen = strlen(curproxy->capture_name);
3461 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003462 curproxy->to_log |= LW_COOKIE;
3463 }
3464 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3465 struct cap_hdr *hdr;
3466
3467 if (curproxy == &defproxy) {
3468 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 +02003469 err_code |= ERR_ALERT | ERR_FATAL;
3470 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003471 }
3472
William Lallemand1a748ae2015-05-19 16:37:23 +02003473 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3474 goto out;
3475
Willy Tarreaubaaee002006-06-26 02:48:02 +02003476 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3477 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3478 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003479 err_code |= ERR_ALERT | ERR_FATAL;
3480 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003481 }
3482
3483 hdr = calloc(sizeof(struct cap_hdr), 1);
3484 hdr->next = curproxy->req_cap;
3485 hdr->name = strdup(args[3]);
3486 hdr->namelen = strlen(args[3]);
3487 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003488 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003489 hdr->index = curproxy->nb_req_cap++;
3490 curproxy->req_cap = hdr;
3491 curproxy->to_log |= LW_REQHDR;
3492 }
3493 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3494 struct cap_hdr *hdr;
3495
3496 if (curproxy == &defproxy) {
3497 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 +02003498 err_code |= ERR_ALERT | ERR_FATAL;
3499 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003500 }
3501
William Lallemand1a748ae2015-05-19 16:37:23 +02003502 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3503 goto out;
3504
Willy Tarreaubaaee002006-06-26 02:48:02 +02003505 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3506 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3507 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003508 err_code |= ERR_ALERT | ERR_FATAL;
3509 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003510 }
3511 hdr = calloc(sizeof(struct cap_hdr), 1);
3512 hdr->next = curproxy->rsp_cap;
3513 hdr->name = strdup(args[3]);
3514 hdr->namelen = strlen(args[3]);
3515 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003516 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003517 hdr->index = curproxy->nb_rsp_cap++;
3518 curproxy->rsp_cap = hdr;
3519 curproxy->to_log |= LW_RSPHDR;
3520 }
3521 else {
3522 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3523 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003524 err_code |= ERR_ALERT | ERR_FATAL;
3525 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003526 }
3527 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003528 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003529 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003530 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003531
William Lallemanddf1425a2015-04-28 20:17:49 +02003532 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3533 goto out;
3534
Willy Tarreaubaaee002006-06-26 02:48:02 +02003535 if (*(args[1]) == 0) {
3536 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3537 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003538 err_code |= ERR_ALERT | ERR_FATAL;
3539 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003540 }
3541 curproxy->conn_retries = atol(args[1]);
3542 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003543 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003544 struct act_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003545
3546 if (curproxy == &defproxy) {
3547 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3548 err_code |= ERR_ALERT | ERR_FATAL;
3549 goto out;
3550 }
3551
Willy Tarreau20b0de52012-12-24 15:45:22 +01003552 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003553 !LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003554 (LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3555 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_DENY ||
3556 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REDIR ||
3557 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REQ_AUTH)) {
Willy Tarreau20b0de52012-12-24 15:45:22 +01003558 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 +01003559 file, linenum, args[0]);
3560 err_code |= ERR_WARN;
3561 }
3562
Willy Tarreauff011f22011-01-06 17:51:27 +01003563 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003564
Willy Tarreauff011f22011-01-06 17:51:27 +01003565 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003566 err_code |= ERR_ALERT | ERR_ABORT;
3567 goto out;
3568 }
3569
Willy Tarreau5002f572014-04-23 01:32:02 +02003570 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003571 err_code |= warnif_cond_conflicts(rule->cond,
3572 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3573 file, linenum);
3574
Willy Tarreauff011f22011-01-06 17:51:27 +01003575 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003576 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003577 else if (!strcmp(args[0], "http-response")) { /* response access control */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003578 struct act_rule *rule;
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003579
3580 if (curproxy == &defproxy) {
3581 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3582 err_code |= ERR_ALERT | ERR_FATAL;
3583 goto out;
3584 }
3585
3586 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003587 !LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003588 (LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3589 LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_DENY)) {
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003590 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3591 file, linenum, args[0]);
3592 err_code |= ERR_WARN;
3593 }
3594
3595 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3596
3597 if (!rule) {
3598 err_code |= ERR_ALERT | ERR_ABORT;
3599 goto out;
3600 }
3601
3602 err_code |= warnif_cond_conflicts(rule->cond,
3603 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3604 file, linenum);
3605
3606 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3607 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003608 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3609 /* set the header name and length into the proxy structure */
3610 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3611 err_code |= ERR_WARN;
3612
3613 if (!*args[1]) {
3614 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3615 file, linenum, args[0]);
3616 err_code |= ERR_ALERT | ERR_FATAL;
3617 goto out;
3618 }
3619
3620 /* set the desired header name */
3621 free(curproxy->server_id_hdr_name);
3622 curproxy->server_id_hdr_name = strdup(args[1]);
3623 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3624 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003625 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003626 struct act_rule *rule;
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003627
Willy Tarreaub099aca2008-10-12 17:26:37 +02003628 if (curproxy == &defproxy) {
3629 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003630 err_code |= ERR_ALERT | ERR_FATAL;
3631 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003632 }
3633
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003634 /* emulate "block" using "http-request block". Since these rules are supposed to
3635 * be processed before all http-request rules, we put them into their own list
3636 * and will insert them at the end.
3637 */
3638 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3639 if (!rule) {
3640 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003641 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003642 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003643 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3644 err_code |= warnif_cond_conflicts(rule->cond,
3645 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3646 file, linenum);
3647 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003648
3649 if (!already_warned(WARN_BLOCK_DEPRECATED))
3650 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]);
3651
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003652 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003653 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003654 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003655
Cyril Bonté99ed3272010-01-24 23:29:44 +01003656 if (curproxy == &defproxy) {
3657 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3658 err_code |= ERR_ALERT | ERR_FATAL;
3659 goto out;
3660 }
3661
Willy Tarreaube4653b2015-05-28 15:26:58 +02003662 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003663 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3664 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003665 err_code |= ERR_ALERT | ERR_FATAL;
3666 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003667 }
3668
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003669 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003670 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003671 err_code |= warnif_cond_conflicts(rule->cond,
3672 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3673 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003674 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003675 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003676 struct switching_rule *rule;
3677
Willy Tarreaub099aca2008-10-12 17:26:37 +02003678 if (curproxy == &defproxy) {
3679 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003680 err_code |= ERR_ALERT | ERR_FATAL;
3681 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003682 }
3683
Willy Tarreau55ea7572007-06-17 19:56:27 +02003684 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003685 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003686
3687 if (*(args[1]) == 0) {
3688 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003689 err_code |= ERR_ALERT | ERR_FATAL;
3690 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003691 }
3692
Willy Tarreauf51658d2014-04-23 01:21:56 +02003693 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3694 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3695 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3696 file, linenum, errmsg);
3697 err_code |= ERR_ALERT | ERR_FATAL;
3698 goto out;
3699 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003700
Willy Tarreauf51658d2014-04-23 01:21:56 +02003701 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003702 }
3703
3704 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
3705 rule->cond = cond;
3706 rule->be.name = strdup(args[1]);
3707 LIST_INIT(&rule->list);
3708 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3709 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003710 else if (strcmp(args[0], "use-server") == 0) {
3711 struct server_rule *rule;
3712
3713 if (curproxy == &defproxy) {
3714 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3715 err_code |= ERR_ALERT | ERR_FATAL;
3716 goto out;
3717 }
3718
3719 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3720 err_code |= ERR_WARN;
3721
3722 if (*(args[1]) == 0) {
3723 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3724 err_code |= ERR_ALERT | ERR_FATAL;
3725 goto out;
3726 }
3727
3728 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3729 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3730 file, linenum, args[0]);
3731 err_code |= ERR_ALERT | ERR_FATAL;
3732 goto out;
3733 }
3734
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003735 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3736 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3737 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003738 err_code |= ERR_ALERT | ERR_FATAL;
3739 goto out;
3740 }
3741
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003742 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003743
3744 rule = (struct server_rule *)calloc(1, sizeof(*rule));
3745 rule->cond = cond;
3746 rule->srv.name = strdup(args[1]);
3747 LIST_INIT(&rule->list);
3748 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3749 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3750 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003751 else if ((!strcmp(args[0], "force-persist")) ||
3752 (!strcmp(args[0], "ignore-persist"))) {
3753 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003754
3755 if (curproxy == &defproxy) {
3756 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3757 err_code |= ERR_ALERT | ERR_FATAL;
3758 goto out;
3759 }
3760
3761 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3762 err_code |= ERR_WARN;
3763
Willy Tarreauef6494c2010-01-28 17:12:36 +01003764 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003765 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3766 file, linenum, args[0]);
3767 err_code |= ERR_ALERT | ERR_FATAL;
3768 goto out;
3769 }
3770
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003771 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3772 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3773 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003774 err_code |= ERR_ALERT | ERR_FATAL;
3775 goto out;
3776 }
3777
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003778 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3779 * where force-persist is applied.
3780 */
3781 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003782
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003783 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003784 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003785 if (!strcmp(args[0], "force-persist")) {
3786 rule->type = PERSIST_TYPE_FORCE;
3787 } else {
3788 rule->type = PERSIST_TYPE_IGNORE;
3789 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003790 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003791 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003792 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003793 else if (!strcmp(args[0], "stick-table")) {
3794 int myidx = 1;
Willy Tarreaue45288c2015-05-26 10:49:46 +02003795 struct proxy *other;
3796
Willy Tarreaue2dc1fa2015-05-26 12:08:07 +02003797 other = proxy_tbl_by_name(curproxy->id);
Willy Tarreaue45288c2015-05-26 10:49:46 +02003798 if (other) {
3799 Alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
3800 file, linenum, curproxy->id, proxy_type_str(other), other->id, other->conf.file, other->conf.line);
3801 err_code |= ERR_ALERT | ERR_FATAL;
3802 goto out;
3803 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003804
Emeric Brun32da3c42010-09-23 18:39:19 +02003805 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003806 curproxy->table.type = (unsigned int)-1;
3807 while (*args[myidx]) {
3808 const char *err;
3809
3810 if (strcmp(args[myidx], "size") == 0) {
3811 myidx++;
3812 if (!*(args[myidx])) {
3813 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3814 file, linenum, args[myidx-1]);
3815 err_code |= ERR_ALERT | ERR_FATAL;
3816 goto out;
3817 }
3818 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3819 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3820 file, linenum, *err, args[myidx-1]);
3821 err_code |= ERR_ALERT | ERR_FATAL;
3822 goto out;
3823 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003824 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003825 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003826 else if (strcmp(args[myidx], "peers") == 0) {
3827 myidx++;
Godbach50523162013-12-11 19:48:57 +08003828 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003829 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3830 file, linenum, args[myidx-1]);
3831 err_code |= ERR_ALERT | ERR_FATAL;
3832 goto out;
Godbach50523162013-12-11 19:48:57 +08003833 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003834 curproxy->table.peers.name = strdup(args[myidx++]);
3835 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003836 else if (strcmp(args[myidx], "expire") == 0) {
3837 myidx++;
3838 if (!*(args[myidx])) {
3839 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3840 file, linenum, args[myidx-1]);
3841 err_code |= ERR_ALERT | ERR_FATAL;
3842 goto out;
3843 }
3844 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3845 if (err) {
3846 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3847 file, linenum, *err, args[myidx-1]);
3848 err_code |= ERR_ALERT | ERR_FATAL;
3849 goto out;
3850 }
3851 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003852 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003853 }
3854 else if (strcmp(args[myidx], "nopurge") == 0) {
3855 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003856 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003857 }
3858 else if (strcmp(args[myidx], "type") == 0) {
3859 myidx++;
3860 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3861 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3862 file, linenum, args[myidx]);
3863 err_code |= ERR_ALERT | ERR_FATAL;
3864 goto out;
3865 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003866 /* myidx already points to next arg */
3867 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003868 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003869 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003870 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003871
3872 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003873 nw = args[myidx];
3874 while (*nw) {
3875 /* the "store" keyword supports a comma-separated list */
3876 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003877 sa = NULL; /* store arg */
3878 while (*nw && *nw != ',') {
3879 if (*nw == '(') {
3880 *nw = 0;
3881 sa = ++nw;
3882 while (*nw != ')') {
3883 if (!*nw) {
3884 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3885 file, linenum, args[0], cw);
3886 err_code |= ERR_ALERT | ERR_FATAL;
3887 goto out;
3888 }
3889 nw++;
3890 }
3891 *nw = '\0';
3892 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003893 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003894 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003895 if (*nw)
3896 *nw++ = '\0';
3897 type = stktable_get_data_type(cw);
3898 if (type < 0) {
3899 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3900 file, linenum, args[0], cw);
3901 err_code |= ERR_ALERT | ERR_FATAL;
3902 goto out;
3903 }
Willy Tarreauac782882010-06-20 10:41:54 +02003904
3905 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3906 switch (err) {
3907 case PE_NONE: break;
3908 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003909 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3910 file, linenum, args[0], cw);
3911 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003912 break;
3913
3914 case PE_ARG_MISSING:
3915 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3916 file, linenum, args[0], cw);
3917 err_code |= ERR_ALERT | ERR_FATAL;
3918 goto out;
3919
3920 case PE_ARG_NOT_USED:
3921 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3922 file, linenum, args[0], cw);
3923 err_code |= ERR_ALERT | ERR_FATAL;
3924 goto out;
3925
3926 default:
3927 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3928 file, linenum, args[0], cw);
3929 err_code |= ERR_ALERT | ERR_FATAL;
3930 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003931 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003932 }
3933 myidx++;
3934 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003935 else {
3936 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3937 file, linenum, args[myidx]);
3938 err_code |= ERR_ALERT | ERR_FATAL;
3939 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003940 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003941 }
3942
3943 if (!curproxy->table.size) {
3944 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3945 file, linenum);
3946 err_code |= ERR_ALERT | ERR_FATAL;
3947 goto out;
3948 }
3949
3950 if (curproxy->table.type == (unsigned int)-1) {
3951 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3952 file, linenum);
3953 err_code |= ERR_ALERT | ERR_FATAL;
3954 goto out;
3955 }
3956 }
3957 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003958 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003959 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003960 int myidx = 0;
3961 const char *name = NULL;
3962 int flags;
3963
3964 if (curproxy == &defproxy) {
3965 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3966 err_code |= ERR_ALERT | ERR_FATAL;
3967 goto out;
3968 }
3969
3970 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3971 err_code |= ERR_WARN;
3972 goto out;
3973 }
3974
3975 myidx++;
3976 if ((strcmp(args[myidx], "store") == 0) ||
3977 (strcmp(args[myidx], "store-request") == 0)) {
3978 myidx++;
3979 flags = STK_IS_STORE;
3980 }
3981 else if (strcmp(args[myidx], "store-response") == 0) {
3982 myidx++;
3983 flags = STK_IS_STORE | STK_ON_RSP;
3984 }
3985 else if (strcmp(args[myidx], "match") == 0) {
3986 myidx++;
3987 flags = STK_IS_MATCH;
3988 }
3989 else if (strcmp(args[myidx], "on") == 0) {
3990 myidx++;
3991 flags = STK_IS_MATCH | STK_IS_STORE;
3992 }
3993 else {
3994 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3995 err_code |= ERR_ALERT | ERR_FATAL;
3996 goto out;
3997 }
3998
3999 if (*(args[myidx]) == 0) {
4000 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
4001 err_code |= ERR_ALERT | ERR_FATAL;
4002 goto out;
4003 }
4004
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004005 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01004006 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004007 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01004008 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004009 err_code |= ERR_ALERT | ERR_FATAL;
4010 goto out;
4011 }
4012
4013 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01004014 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
4015 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
4016 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004017 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004018 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004019 goto out;
4020 }
4021 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01004022 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
4023 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
4024 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004025 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004026 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004027 goto out;
4028 }
4029 }
4030
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004031 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01004032 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004033
Emeric Brunb982a3d2010-01-04 15:45:53 +01004034 if (strcmp(args[myidx], "table") == 0) {
4035 myidx++;
4036 name = args[myidx++];
4037 }
4038
Willy Tarreauef6494c2010-01-28 17:12:36 +01004039 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004040 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
4041 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
4042 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004043 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004044 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004045 goto out;
4046 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004047 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01004048 else if (*(args[myidx])) {
4049 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
4050 file, linenum, args[0], args[myidx]);
4051 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004052 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01004053 goto out;
4054 }
Emeric Brun97679e72010-09-23 17:56:44 +02004055 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004056 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02004057 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004058 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01004059
Emeric Brunb982a3d2010-01-04 15:45:53 +01004060 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
4061 rule->cond = cond;
4062 rule->expr = expr;
4063 rule->flags = flags;
4064 rule->table.name = name ? strdup(name) : NULL;
4065 LIST_INIT(&rule->list);
4066 if (flags & STK_ON_RSP)
4067 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
4068 else
4069 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
4070 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004071 else if (!strcmp(args[0], "stats")) {
4072 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
4073 curproxy->uri_auth = NULL; /* we must detach from the default config */
4074
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004075 if (!*args[1]) {
4076 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02004077 } else if (!strcmp(args[1], "admin")) {
4078 struct stats_admin_rule *rule;
4079
4080 if (curproxy == &defproxy) {
4081 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
4082 err_code |= ERR_ALERT | ERR_FATAL;
4083 goto out;
4084 }
4085
4086 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4087 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4088 err_code |= ERR_ALERT | ERR_ABORT;
4089 goto out;
4090 }
4091
4092 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4093 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4094 file, linenum, args[0], args[1]);
4095 err_code |= ERR_ALERT | ERR_FATAL;
4096 goto out;
4097 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004098 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4099 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
4100 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02004101 err_code |= ERR_ALERT | ERR_FATAL;
4102 goto out;
4103 }
4104
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004105 err_code |= warnif_cond_conflicts(cond,
4106 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4107 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02004108
4109 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
4110 rule->cond = cond;
4111 LIST_INIT(&rule->list);
4112 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004113 } else if (!strcmp(args[1], "uri")) {
4114 if (*(args[2]) == 0) {
4115 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004116 err_code |= ERR_ALERT | ERR_FATAL;
4117 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004118 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
4119 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004120 err_code |= ERR_ALERT | ERR_ABORT;
4121 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004122 }
4123 } else if (!strcmp(args[1], "realm")) {
4124 if (*(args[2]) == 0) {
4125 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004126 err_code |= ERR_ALERT | ERR_FATAL;
4127 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004128 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
4129 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004130 err_code |= ERR_ALERT | ERR_ABORT;
4131 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004132 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02004133 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004134 unsigned interval;
4135
4136 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
4137 if (err) {
4138 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
4139 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004140 err_code |= ERR_ALERT | ERR_FATAL;
4141 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004142 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
4143 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004144 err_code |= ERR_ALERT | ERR_ABORT;
4145 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004146 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004147 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004148 struct act_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004149
4150 if (curproxy == &defproxy) {
4151 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4152 err_code |= ERR_ALERT | ERR_FATAL;
4153 goto out;
4154 }
4155
4156 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4157 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4158 err_code |= ERR_ALERT | ERR_ABORT;
4159 goto out;
4160 }
4161
Willy Tarreauff011f22011-01-06 17:51:27 +01004162 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004163 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct act_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004164 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
4165 file, linenum, args[0]);
4166 err_code |= ERR_WARN;
4167 }
4168
Willy Tarreauff011f22011-01-06 17:51:27 +01004169 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004170
Willy Tarreauff011f22011-01-06 17:51:27 +01004171 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004172 err_code |= ERR_ALERT | ERR_ABORT;
4173 goto out;
4174 }
4175
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004176 err_code |= warnif_cond_conflicts(rule->cond,
4177 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4178 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01004179 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004180
Willy Tarreaubaaee002006-06-26 02:48:02 +02004181 } else if (!strcmp(args[1], "auth")) {
4182 if (*(args[2]) == 0) {
4183 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004184 err_code |= ERR_ALERT | ERR_FATAL;
4185 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004186 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
4187 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004188 err_code |= ERR_ALERT | ERR_ABORT;
4189 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004190 }
4191 } else if (!strcmp(args[1], "scope")) {
4192 if (*(args[2]) == 0) {
4193 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004194 err_code |= ERR_ALERT | ERR_FATAL;
4195 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004196 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
4197 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004198 err_code |= ERR_ALERT | ERR_ABORT;
4199 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004200 }
4201 } else if (!strcmp(args[1], "enable")) {
4202 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4203 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004204 err_code |= ERR_ALERT | ERR_ABORT;
4205 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004206 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004207 } else if (!strcmp(args[1], "hide-version")) {
4208 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
4209 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004210 err_code |= ERR_ALERT | ERR_ABORT;
4211 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004212 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01004213 } else if (!strcmp(args[1], "show-legends")) {
4214 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
4215 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4216 err_code |= ERR_ALERT | ERR_ABORT;
4217 goto out;
4218 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004219 } else if (!strcmp(args[1], "show-node")) {
4220
4221 if (*args[2]) {
4222 int i;
4223 char c;
4224
4225 for (i=0; args[2][i]; i++) {
4226 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01004227 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
4228 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004229 break;
4230 }
4231
4232 if (!i || args[2][i]) {
4233 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
4234 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
4235 file, linenum, args[0], args[1]);
4236 err_code |= ERR_ALERT | ERR_FATAL;
4237 goto out;
4238 }
4239 }
4240
4241 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
4242 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4243 err_code |= ERR_ALERT | ERR_ABORT;
4244 goto out;
4245 }
4246 } else if (!strcmp(args[1], "show-desc")) {
4247 char *desc = NULL;
4248
4249 if (*args[2]) {
4250 int i, len=0;
4251 char *d;
4252
Willy Tarreau348acfe2014-04-14 15:00:39 +02004253 for (i = 2; *args[i]; i++)
4254 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004255
4256 desc = d = (char *)calloc(1, len);
4257
Willy Tarreau348acfe2014-04-14 15:00:39 +02004258 d += snprintf(d, desc + len - d, "%s", args[2]);
4259 for (i = 3; *args[i]; i++)
4260 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004261 }
4262
4263 if (!*args[2] && !global.desc)
4264 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
4265 file, linenum, args[1]);
4266 else {
4267 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
4268 free(desc);
4269 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4270 err_code |= ERR_ALERT | ERR_ABORT;
4271 goto out;
4272 }
4273 free(desc);
4274 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004275 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004276stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02004277 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 +01004278 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004279 err_code |= ERR_ALERT | ERR_FATAL;
4280 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004281 }
4282 }
4283 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004284 int optnum;
4285
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004286 if (*(args[1]) == '\0') {
4287 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
4288 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004289 err_code |= ERR_ALERT | ERR_FATAL;
4290 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004291 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01004292
4293 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
4294 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004295 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
4296 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4297 file, linenum, cfg_opts[optnum].name);
4298 err_code |= ERR_ALERT | ERR_FATAL;
4299 goto out;
4300 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004301 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4302 goto out;
4303
Willy Tarreau93893792009-07-23 13:19:11 +02004304 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
4305 err_code |= ERR_WARN;
4306 goto out;
4307 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004308
Willy Tarreau3842f002009-06-14 11:39:52 +02004309 curproxy->no_options &= ~cfg_opts[optnum].val;
4310 curproxy->options &= ~cfg_opts[optnum].val;
4311
4312 switch (kwm) {
4313 case KWM_STD:
4314 curproxy->options |= cfg_opts[optnum].val;
4315 break;
4316 case KWM_NO:
4317 curproxy->no_options |= cfg_opts[optnum].val;
4318 break;
4319 case KWM_DEF: /* already cleared */
4320 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004321 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004322
Willy Tarreau93893792009-07-23 13:19:11 +02004323 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004324 }
4325 }
4326
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004327 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
4328 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004329 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
4330 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4331 file, linenum, cfg_opts2[optnum].name);
4332 err_code |= ERR_ALERT | ERR_FATAL;
4333 goto out;
4334 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004335 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4336 goto out;
Willy Tarreau93893792009-07-23 13:19:11 +02004337 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4338 err_code |= ERR_WARN;
4339 goto out;
4340 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004341
Willy Tarreau3842f002009-06-14 11:39:52 +02004342 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4343 curproxy->options2 &= ~cfg_opts2[optnum].val;
4344
4345 switch (kwm) {
4346 case KWM_STD:
4347 curproxy->options2 |= cfg_opts2[optnum].val;
4348 break;
4349 case KWM_NO:
4350 curproxy->no_options2 |= cfg_opts2[optnum].val;
4351 break;
4352 case KWM_DEF: /* already cleared */
4353 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004354 }
Willy Tarreau93893792009-07-23 13:19:11 +02004355 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004356 }
4357 }
4358
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004359 /* HTTP options override each other. They can be cancelled using
4360 * "no option xxx" which only switches to default mode if the mode
4361 * was this one (useful for cancelling options set in defaults
4362 * sections).
4363 */
4364 if (strcmp(args[1], "httpclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004365 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4366 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004367 if (kwm == KWM_STD) {
4368 curproxy->options &= ~PR_O_HTTP_MODE;
4369 curproxy->options |= PR_O_HTTP_PCL;
4370 goto out;
4371 }
4372 else if (kwm == KWM_NO) {
4373 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4374 curproxy->options &= ~PR_O_HTTP_MODE;
4375 goto out;
4376 }
4377 }
4378 else if (strcmp(args[1], "forceclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004379 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4380 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004381 if (kwm == KWM_STD) {
4382 curproxy->options &= ~PR_O_HTTP_MODE;
4383 curproxy->options |= PR_O_HTTP_FCL;
4384 goto out;
4385 }
4386 else if (kwm == KWM_NO) {
4387 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4388 curproxy->options &= ~PR_O_HTTP_MODE;
4389 goto out;
4390 }
4391 }
4392 else if (strcmp(args[1], "http-server-close") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004393 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4394 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004395 if (kwm == KWM_STD) {
4396 curproxy->options &= ~PR_O_HTTP_MODE;
4397 curproxy->options |= PR_O_HTTP_SCL;
4398 goto out;
4399 }
4400 else if (kwm == KWM_NO) {
4401 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4402 curproxy->options &= ~PR_O_HTTP_MODE;
4403 goto out;
4404 }
4405 }
4406 else if (strcmp(args[1], "http-keep-alive") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004407 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4408 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004409 if (kwm == KWM_STD) {
4410 curproxy->options &= ~PR_O_HTTP_MODE;
4411 curproxy->options |= PR_O_HTTP_KAL;
4412 goto out;
4413 }
4414 else if (kwm == KWM_NO) {
4415 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4416 curproxy->options &= ~PR_O_HTTP_MODE;
4417 goto out;
4418 }
4419 }
4420 else if (strcmp(args[1], "http-tunnel") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004421 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4422 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004423 if (kwm == KWM_STD) {
4424 curproxy->options &= ~PR_O_HTTP_MODE;
4425 curproxy->options |= PR_O_HTTP_TUN;
4426 goto out;
4427 }
4428 else if (kwm == KWM_NO) {
4429 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4430 curproxy->options &= ~PR_O_HTTP_MODE;
4431 goto out;
4432 }
4433 }
4434
Joseph Lynch726ab712015-05-11 23:25:34 -07004435 /* Redispatch can take an integer argument that control when the
4436 * resispatch occurs. All values are relative to the retries option.
4437 * This can be cancelled using "no option xxx".
4438 */
4439 if (strcmp(args[1], "redispatch") == 0) {
4440 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
4441 err_code |= ERR_WARN;
4442 goto out;
4443 }
4444
4445 curproxy->no_options &= ~PR_O_REDISP;
4446 curproxy->options &= ~PR_O_REDISP;
4447
4448 switch (kwm) {
4449 case KWM_STD:
4450 curproxy->options |= PR_O_REDISP;
4451 curproxy->redispatch_after = -1;
4452 if(*args[2]) {
4453 curproxy->redispatch_after = atol(args[2]);
4454 }
4455 break;
4456 case KWM_NO:
4457 curproxy->no_options |= PR_O_REDISP;
4458 curproxy->redispatch_after = 0;
4459 break;
4460 case KWM_DEF: /* already cleared */
4461 break;
4462 }
4463 goto out;
4464 }
4465
Willy Tarreau3842f002009-06-14 11:39:52 +02004466 if (kwm != KWM_STD) {
4467 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004468 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004469 err_code |= ERR_ALERT | ERR_FATAL;
4470 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004471 }
4472
Emeric Brun3a058f32009-06-30 18:26:00 +02004473 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004474 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004475 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004476 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004477 if (*(args[2]) != '\0') {
4478 if (!strcmp(args[2], "clf")) {
4479 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004480 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004481 } else {
William Lallemand77063bc2015-05-28 18:02:48 +02004482 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004483 err_code |= ERR_ALERT | ERR_FATAL;
4484 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004485 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004486 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
4487 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004488 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004489 if (curproxy->conf.logformat_string != default_http_log_format &&
4490 curproxy->conf.logformat_string != default_tcp_log_format &&
4491 curproxy->conf.logformat_string != clf_http_log_format)
4492 free(curproxy->conf.logformat_string);
4493 curproxy->conf.logformat_string = logformat;
4494
4495 free(curproxy->conf.lfs_file);
4496 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4497 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004498 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004499 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004500 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004501 if (curproxy->conf.logformat_string != default_http_log_format &&
4502 curproxy->conf.logformat_string != default_tcp_log_format &&
4503 curproxy->conf.logformat_string != clf_http_log_format)
4504 free(curproxy->conf.logformat_string);
4505 curproxy->conf.logformat_string = default_tcp_log_format;
4506
4507 free(curproxy->conf.lfs_file);
4508 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4509 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemanddf1425a2015-04-28 20:17:49 +02004510
4511 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4512 goto out;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004513 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004514 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004515 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004516 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004517 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004518
William Lallemanddf1425a2015-04-28 20:17:49 +02004519 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4520 goto out;
4521
Willy Tarreau13943ab2006-12-31 00:24:10 +01004522 if (curproxy->cap & PR_CAP_FE)
4523 curproxy->options |= PR_O_TCP_CLI_KA;
4524 if (curproxy->cap & PR_CAP_BE)
4525 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004526 }
4527 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004528 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004529 err_code |= ERR_WARN;
4530
Willy Tarreaubaaee002006-06-26 02:48:02 +02004531 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004532 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004533 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004534 curproxy->options2 &= ~PR_O2_CHK_ANY;
4535 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004536 if (!*args[2]) { /* no argument */
4537 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4538 curproxy->check_len = strlen(DEF_CHECK_REQ);
4539 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004540 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004541 curproxy->check_req = (char *)malloc(reqlen);
4542 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004543 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004544 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004545 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004546 if (*args[4])
4547 reqlen += strlen(args[4]);
4548 else
4549 reqlen += strlen("HTTP/1.0");
4550
4551 curproxy->check_req = (char *)malloc(reqlen);
4552 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004553 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004554 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004555 if (alertif_too_many_args_idx(3, 1, file, linenum, args, &err_code))
4556 goto out;
Willy Tarreauf3c69202006-07-09 16:42:34 +02004557 }
4558 else if (!strcmp(args[1], "ssl-hello-chk")) {
4559 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004560 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004561 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004562
Willy Tarreaua534fea2008-08-03 12:19:50 +02004563 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004564 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004565 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004566 curproxy->options2 |= PR_O2_SSL3_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004567
4568 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4569 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004570 }
Willy Tarreau23677902007-05-08 23:50:35 +02004571 else if (!strcmp(args[1], "smtpchk")) {
4572 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004573 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004574 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004575 curproxy->options2 &= ~PR_O2_CHK_ANY;
4576 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004577
4578 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4579 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4580 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4581 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4582 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4583 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
4584 curproxy->check_req = (char *)malloc(reqlen);
4585 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4586 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4587 } else {
4588 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4589 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4590 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4591 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4592 }
4593 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004594 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4595 goto out;
Willy Tarreau23677902007-05-08 23:50:35 +02004596 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004597 else if (!strcmp(args[1], "pgsql-check")) {
4598 /* use PostgreSQL request to check servers' health */
4599 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4600 err_code |= ERR_WARN;
4601
4602 free(curproxy->check_req);
4603 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004604 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004605 curproxy->options2 |= PR_O2_PGSQL_CHK;
4606
4607 if (*(args[2])) {
4608 int cur_arg = 2;
4609
4610 while (*(args[cur_arg])) {
4611 if (strcmp(args[cur_arg], "user") == 0) {
4612 char * packet;
4613 uint32_t packet_len;
4614 uint32_t pv;
4615
4616 /* suboption header - needs additional argument for it */
4617 if (*(args[cur_arg+1]) == 0) {
4618 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4619 file, linenum, args[0], args[1], args[cur_arg]);
4620 err_code |= ERR_ALERT | ERR_FATAL;
4621 goto out;
4622 }
4623
4624 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4625 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4626 pv = htonl(0x30000); /* protocol version 3.0 */
4627
4628 packet = (char*) calloc(1, packet_len);
4629
4630 memcpy(packet + 4, &pv, 4);
4631
4632 /* copy "user" */
4633 memcpy(packet + 8, "user", 4);
4634
4635 /* copy username */
4636 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4637
4638 free(curproxy->check_req);
4639 curproxy->check_req = packet;
4640 curproxy->check_len = packet_len;
4641
4642 packet_len = htonl(packet_len);
4643 memcpy(packet, &packet_len, 4);
4644 cur_arg += 2;
4645 } else {
4646 /* unknown suboption - catchall */
4647 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4648 file, linenum, args[0], args[1]);
4649 err_code |= ERR_ALERT | ERR_FATAL;
4650 goto out;
4651 }
4652 } /* end while loop */
4653 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004654 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4655 goto out;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004656 }
4657
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004658 else if (!strcmp(args[1], "redis-check")) {
4659 /* use REDIS PING request to check servers' health */
4660 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4661 err_code |= ERR_WARN;
4662
4663 free(curproxy->check_req);
4664 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004665 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004666 curproxy->options2 |= PR_O2_REDIS_CHK;
4667
4668 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
4669 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4670 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004671
4672 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4673 goto out;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004674 }
4675
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004676 else if (!strcmp(args[1], "mysql-check")) {
4677 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004678 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4679 err_code |= ERR_WARN;
4680
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004681 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004682 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004683 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004684 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004685
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004686 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004687 * const char mysql40_client_auth_pkt[] = {
4688 * "\x0e\x00\x00" // packet length
4689 * "\x01" // packet number
4690 * "\x00\x00" // client capabilities
4691 * "\x00\x00\x01" // max packet
4692 * "haproxy\x00" // username (null terminated string)
4693 * "\x00" // filler (always 0x00)
4694 * "\x01\x00\x00" // packet length
4695 * "\x00" // packet number
4696 * "\x01" // COM_QUIT command
4697 * };
4698 */
4699
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004700 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4701 * const char mysql41_client_auth_pkt[] = {
4702 * "\x0e\x00\x00\" // packet length
4703 * "\x01" // packet number
4704 * "\x00\x00\x00\x00" // client capabilities
4705 * "\x00\x00\x00\x01" // max packet
4706 * "\x21" // character set (UTF-8)
4707 * char[23] // All zeroes
4708 * "haproxy\x00" // username (null terminated string)
4709 * "\x00" // filler (always 0x00)
4710 * "\x01\x00\x00" // packet length
4711 * "\x00" // packet number
4712 * "\x01" // COM_QUIT command
4713 * };
4714 */
4715
4716
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004717 if (*(args[2])) {
4718 int cur_arg = 2;
4719
4720 while (*(args[cur_arg])) {
4721 if (strcmp(args[cur_arg], "user") == 0) {
4722 char *mysqluser;
4723 int packetlen, reqlen, userlen;
4724
4725 /* suboption header - needs additional argument for it */
4726 if (*(args[cur_arg+1]) == 0) {
4727 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4728 file, linenum, args[0], args[1], args[cur_arg]);
4729 err_code |= ERR_ALERT | ERR_FATAL;
4730 goto out;
4731 }
4732 mysqluser = args[cur_arg + 1];
4733 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004734
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004735 if (*(args[cur_arg+2])) {
4736 if (!strcmp(args[cur_arg+2], "post-41")) {
4737 packetlen = userlen + 7 + 27;
4738 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004739
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004740 free(curproxy->check_req);
4741 curproxy->check_req = (char *)calloc(1, reqlen);
4742 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004743
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004744 snprintf(curproxy->check_req, 4, "%c%c%c",
4745 ((unsigned char) packetlen & 0xff),
4746 ((unsigned char) (packetlen >> 8) & 0xff),
4747 ((unsigned char) (packetlen >> 16) & 0xff));
4748
4749 curproxy->check_req[3] = 1;
4750 curproxy->check_req[5] = 130;
4751 curproxy->check_req[11] = 1;
4752 curproxy->check_req[12] = 33;
4753 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4754 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4755 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4756 cur_arg += 3;
4757 } else {
4758 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4759 err_code |= ERR_ALERT | ERR_FATAL;
4760 goto out;
4761 }
4762 } else {
4763 packetlen = userlen + 7;
4764 reqlen = packetlen + 9;
4765
4766 free(curproxy->check_req);
4767 curproxy->check_req = (char *)calloc(1, reqlen);
4768 curproxy->check_len = reqlen;
4769
4770 snprintf(curproxy->check_req, 4, "%c%c%c",
4771 ((unsigned char) packetlen & 0xff),
4772 ((unsigned char) (packetlen >> 8) & 0xff),
4773 ((unsigned char) (packetlen >> 16) & 0xff));
4774
4775 curproxy->check_req[3] = 1;
4776 curproxy->check_req[5] = 128;
4777 curproxy->check_req[8] = 1;
4778 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4779 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4780 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4781 cur_arg += 2;
4782 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004783 } else {
4784 /* unknown suboption - catchall */
4785 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4786 file, linenum, args[0], args[1]);
4787 err_code |= ERR_ALERT | ERR_FATAL;
4788 goto out;
4789 }
4790 } /* end while loop */
4791 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004792 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004793 else if (!strcmp(args[1], "ldap-check")) {
4794 /* use LDAP request to check servers' health */
4795 free(curproxy->check_req);
4796 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004797 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004798 curproxy->options2 |= PR_O2_LDAP_CHK;
4799
4800 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
4801 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
4802 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004803 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4804 goto out;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004805 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004806 else if (!strcmp(args[1], "tcp-check")) {
4807 /* use raw TCPCHK send/expect to check servers' health */
4808 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4809 err_code |= ERR_WARN;
4810
4811 free(curproxy->check_req);
4812 curproxy->check_req = NULL;
4813 curproxy->options2 &= ~PR_O2_CHK_ANY;
4814 curproxy->options2 |= PR_O2_TCPCHK_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004815 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4816 goto out;
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004817 }
Simon Horman98637e52014-06-20 12:30:16 +09004818 else if (!strcmp(args[1], "external-check")) {
4819 /* excute an external command to check servers' health */
4820 free(curproxy->check_req);
4821 curproxy->check_req = NULL;
4822 curproxy->options2 &= ~PR_O2_CHK_ANY;
4823 curproxy->options2 |= PR_O2_EXT_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004824 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4825 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09004826 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004827 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004828 int cur_arg;
4829
4830 /* insert x-forwarded-for field, but not for the IP address listed as an except.
4831 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004832 */
Ross Westaf72a1d2008-08-03 10:51:45 +02004833
Willy Tarreau87cf5142011-08-19 22:57:24 +02004834 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02004835
4836 free(curproxy->fwdfor_hdr_name);
4837 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
4838 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
4839
4840 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
4841 cur_arg = 2;
4842 while (*(args[cur_arg])) {
4843 if (!strcmp(args[cur_arg], "except")) {
4844 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004845 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004846 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4847 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004848 err_code |= ERR_ALERT | ERR_FATAL;
4849 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004850 }
4851 /* flush useless bits */
4852 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02004853 cur_arg += 2;
4854 } else if (!strcmp(args[cur_arg], "header")) {
4855 /* suboption header - needs additional argument for it */
4856 if (*(args[cur_arg+1]) == 0) {
4857 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4858 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004859 err_code |= ERR_ALERT | ERR_FATAL;
4860 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02004861 }
4862 free(curproxy->fwdfor_hdr_name);
4863 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
4864 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
4865 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02004866 } else if (!strcmp(args[cur_arg], "if-none")) {
4867 curproxy->options &= ~PR_O_FF_ALWAYS;
4868 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004869 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02004870 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02004871 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02004872 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004873 err_code |= ERR_ALERT | ERR_FATAL;
4874 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004875 }
Ross Westaf72a1d2008-08-03 10:51:45 +02004876 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004877 }
Maik Broemme2850cb42009-04-17 18:53:21 +02004878 else if (!strcmp(args[1], "originalto")) {
4879 int cur_arg;
4880
4881 /* insert x-original-to field, but not for the IP address listed as an except.
4882 * set default options (ie: bitfield, header name, etc)
4883 */
4884
4885 curproxy->options |= PR_O_ORGTO;
4886
4887 free(curproxy->orgto_hdr_name);
4888 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
4889 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
4890
Willy Tarreau87cf5142011-08-19 22:57:24 +02004891 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02004892 cur_arg = 2;
4893 while (*(args[cur_arg])) {
4894 if (!strcmp(args[cur_arg], "except")) {
4895 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004896 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 +02004897 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4898 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004899 err_code |= ERR_ALERT | ERR_FATAL;
4900 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004901 }
4902 /* flush useless bits */
4903 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
4904 cur_arg += 2;
4905 } else if (!strcmp(args[cur_arg], "header")) {
4906 /* suboption header - needs additional argument for it */
4907 if (*(args[cur_arg+1]) == 0) {
4908 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4909 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004910 err_code |= ERR_ALERT | ERR_FATAL;
4911 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004912 }
4913 free(curproxy->orgto_hdr_name);
4914 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
4915 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
4916 cur_arg += 2;
4917 } else {
4918 /* unknown suboption - catchall */
4919 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
4920 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004921 err_code |= ERR_ALERT | ERR_FATAL;
4922 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004923 }
4924 } /* end while loop */
4925 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004926 else {
4927 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004928 err_code |= ERR_ALERT | ERR_FATAL;
4929 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004930 }
Willy Tarreau93893792009-07-23 13:19:11 +02004931 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004932 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004933 else if (!strcmp(args[0], "default_backend")) {
4934 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004935 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004936
4937 if (*(args[1]) == 0) {
4938 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004939 err_code |= ERR_ALERT | ERR_FATAL;
4940 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004941 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004942 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004943 curproxy->defbe.name = strdup(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02004944
4945 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
4946 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004947 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004948 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01004949 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004950 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004951
Willy Tarreaua3c504c2014-04-28 22:37:32 +02004952 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
4953 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 +01004954 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004955 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004956 /* enable reconnections to dispatch */
4957 curproxy->options |= PR_O_REDISP;
William Lallemanddf1425a2015-04-28 20:17:49 +02004958
4959 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
4960 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004961 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02004962 else if (!strcmp(args[0], "http-reuse")) {
4963 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4964 err_code |= ERR_WARN;
4965
4966 if (strcmp(args[1], "never") == 0) {
4967 /* enable a graceful server shutdown on an HTTP 404 response */
4968 curproxy->options &= ~PR_O_REUSE_MASK;
4969 curproxy->options |= PR_O_REUSE_NEVR;
4970 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4971 goto out;
4972 }
Willy Tarreau161d45f2015-08-05 16:02:46 +02004973 else if (strcmp(args[1], "safe") == 0) {
4974 /* enable a graceful server shutdown on an HTTP 404 response */
4975 curproxy->options &= ~PR_O_REUSE_MASK;
4976 curproxy->options |= PR_O_REUSE_SAFE;
4977 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4978 goto out;
4979 }
Willy Tarreau449d74a2015-08-05 17:16:33 +02004980 else if (strcmp(args[1], "aggressive") == 0) {
4981 curproxy->options &= ~PR_O_REUSE_MASK;
4982 curproxy->options |= PR_O_REUSE_AGGR;
4983 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4984 goto out;
4985 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02004986 else if (strcmp(args[1], "always") == 0) {
4987 /* enable a graceful server shutdown on an HTTP 404 response */
4988 curproxy->options &= ~PR_O_REUSE_MASK;
4989 curproxy->options |= PR_O_REUSE_ALWS;
4990 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4991 goto out;
4992 }
4993 else {
Willy Tarreau449d74a2015-08-05 17:16:33 +02004994 Alert("parsing [%s:%d] : '%s' only supports 'never', 'safe', 'aggressive', 'always'.\n", file, linenum, args[0]);
Willy Tarreaud8fecee2015-08-05 14:12:31 +02004995 err_code |= ERR_ALERT | ERR_FATAL;
4996 goto out;
4997 }
4998 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004999 else if (!strcmp(args[0], "http-check")) {
5000 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005001 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01005002
5003 if (strcmp(args[1], "disable-on-404") == 0) {
5004 /* enable a graceful server shutdown on an HTTP 404 response */
5005 curproxy->options |= PR_O_DISABLE404;
William Lallemanddf1425a2015-04-28 20:17:49 +02005006 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5007 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005008 }
Willy Tarreauef781042010-01-27 11:53:01 +01005009 else if (strcmp(args[1], "send-state") == 0) {
5010 /* enable emission of the apparent state of a server in HTTP checks */
5011 curproxy->options2 |= PR_O2_CHK_SNDST;
William Lallemanddf1425a2015-04-28 20:17:49 +02005012 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5013 goto out;
Willy Tarreauef781042010-01-27 11:53:01 +01005014 }
Willy Tarreaubd741542010-03-16 18:46:54 +01005015 else if (strcmp(args[1], "expect") == 0) {
5016 const char *ptr_arg;
5017 int cur_arg;
5018
5019 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5020 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5021 err_code |= ERR_ALERT | ERR_FATAL;
5022 goto out;
5023 }
5024
5025 cur_arg = 2;
5026 /* consider exclamation marks, sole or at the beginning of a word */
5027 while (*(ptr_arg = args[cur_arg])) {
5028 while (*ptr_arg == '!') {
5029 curproxy->options2 ^= PR_O2_EXP_INV;
5030 ptr_arg++;
5031 }
5032 if (*ptr_arg)
5033 break;
5034 cur_arg++;
5035 }
5036 /* now ptr_arg points to the beginning of a word past any possible
5037 * exclamation mark, and cur_arg is the argument which holds this word.
5038 */
5039 if (strcmp(ptr_arg, "status") == 0) {
5040 if (!*(args[cur_arg + 1])) {
5041 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5042 file, linenum, args[0], args[1], ptr_arg);
5043 err_code |= ERR_ALERT | ERR_FATAL;
5044 goto out;
5045 }
5046 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005047 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005048 curproxy->expect_str = strdup(args[cur_arg + 1]);
5049 }
5050 else if (strcmp(ptr_arg, "string") == 0) {
5051 if (!*(args[cur_arg + 1])) {
5052 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5053 file, linenum, args[0], args[1], ptr_arg);
5054 err_code |= ERR_ALERT | ERR_FATAL;
5055 goto out;
5056 }
5057 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005058 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005059 curproxy->expect_str = strdup(args[cur_arg + 1]);
5060 }
5061 else if (strcmp(ptr_arg, "rstatus") == 0) {
5062 if (!*(args[cur_arg + 1])) {
5063 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5064 file, linenum, args[0], args[1], ptr_arg);
5065 err_code |= ERR_ALERT | ERR_FATAL;
5066 goto out;
5067 }
5068 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005069 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005070 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005071 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005072 free(curproxy->expect_regex);
5073 curproxy->expect_regex = NULL;
5074 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005075 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005076 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5077 error = NULL;
5078 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5079 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5080 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5081 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005082 err_code |= ERR_ALERT | ERR_FATAL;
5083 goto out;
5084 }
5085 }
5086 else if (strcmp(ptr_arg, "rstring") == 0) {
5087 if (!*(args[cur_arg + 1])) {
5088 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5089 file, linenum, args[0], args[1], ptr_arg);
5090 err_code |= ERR_ALERT | ERR_FATAL;
5091 goto out;
5092 }
5093 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005094 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005095 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005096 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005097 free(curproxy->expect_regex);
5098 curproxy->expect_regex = NULL;
5099 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005100 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005101 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5102 error = NULL;
5103 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5104 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5105 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5106 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005107 err_code |= ERR_ALERT | ERR_FATAL;
5108 goto out;
5109 }
5110 }
5111 else {
5112 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
5113 file, linenum, args[0], args[1], ptr_arg);
5114 err_code |= ERR_ALERT | ERR_FATAL;
5115 goto out;
5116 }
5117 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005118 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005119 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 +02005120 err_code |= ERR_ALERT | ERR_FATAL;
5121 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005122 }
5123 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005124 else if (!strcmp(args[0], "tcp-check")) {
5125 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5126 err_code |= ERR_WARN;
5127
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005128 if (strcmp(args[1], "comment") == 0) {
5129 int cur_arg;
5130 struct tcpcheck_rule *tcpcheck;
5131
5132 cur_arg = 1;
5133 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5134 tcpcheck->action = TCPCHK_ACT_COMMENT;
5135
5136 if (!*args[cur_arg + 1]) {
5137 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5138 file, linenum, args[cur_arg]);
5139 err_code |= ERR_ALERT | ERR_FATAL;
5140 goto out;
5141 }
5142
5143 tcpcheck->comment = strdup(args[cur_arg + 1]);
5144
5145 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
William Lallemanddf1425a2015-04-28 20:17:49 +02005146 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
5147 goto out;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005148 }
5149 else if (strcmp(args[1], "connect") == 0) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005150 const char *ptr_arg;
5151 int cur_arg;
5152 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005153
5154 /* check if first rule is also a 'connect' action */
Willy Tarreau5581c272015-05-13 12:24:53 +02005155 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
5156 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
5157 tcpcheck->action == TCPCHK_ACT_COMMENT) {
5158 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
5159 }
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005160
Willy Tarreau5581c272015-05-13 12:24:53 +02005161 if (&tcpcheck->list != &curproxy->tcpcheck_rules
5162 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
5163 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
5164 file, linenum);
5165 err_code |= ERR_ALERT | ERR_FATAL;
5166 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005167 }
5168
5169 cur_arg = 2;
5170 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5171 tcpcheck->action = TCPCHK_ACT_CONNECT;
5172
5173 /* parsing each parameters to fill up the rule */
5174 while (*(ptr_arg = args[cur_arg])) {
5175 /* tcp port */
5176 if (strcmp(args[cur_arg], "port") == 0) {
5177 if ( (atol(args[cur_arg + 1]) > 65535) ||
5178 (atol(args[cur_arg + 1]) < 1) ){
5179 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
5180 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
5181 err_code |= ERR_ALERT | ERR_FATAL;
5182 goto out;
5183 }
5184 tcpcheck->port = atol(args[cur_arg + 1]);
5185 cur_arg += 2;
5186 }
5187 /* send proxy protocol */
5188 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
5189 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
5190 cur_arg++;
5191 }
5192#ifdef USE_OPENSSL
5193 else if (strcmp(args[cur_arg], "ssl") == 0) {
5194 curproxy->options |= PR_O_TCPCHK_SSL;
5195 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
5196 cur_arg++;
5197 }
5198#endif /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005199 /* comment for this tcpcheck line */
5200 else if (strcmp(args[cur_arg], "comment") == 0) {
5201 if (!*args[cur_arg + 1]) {
5202 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5203 file, linenum, args[cur_arg]);
5204 err_code |= ERR_ALERT | ERR_FATAL;
5205 goto out;
5206 }
5207 tcpcheck->comment = strdup(args[cur_arg + 1]);
5208 cur_arg += 2;
5209 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005210 else {
5211#ifdef USE_OPENSSL
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005212 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 +01005213#else /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005214 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 +01005215#endif /* USE_OPENSSL */
5216 file, linenum, args[0], args[1], args[cur_arg]);
5217 err_code |= ERR_ALERT | ERR_FATAL;
5218 goto out;
5219 }
5220
5221 }
5222
5223 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5224 }
5225 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005226 if (! *(args[2]) ) {
5227 /* SEND string expected */
5228 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
5229 file, linenum, args[0], args[1], args[2]);
5230 err_code |= ERR_ALERT | ERR_FATAL;
5231 goto out;
5232 } else {
5233 struct tcpcheck_rule *tcpcheck;
5234
5235 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5236
5237 tcpcheck->action = TCPCHK_ACT_SEND;
5238 tcpcheck->string_len = strlen(args[2]);
5239 tcpcheck->string = strdup(args[2]);
5240 tcpcheck->expect_regex = NULL;
5241
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005242 /* comment for this tcpcheck line */
5243 if (strcmp(args[3], "comment") == 0) {
5244 if (!*args[4]) {
5245 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5246 file, linenum, args[3]);
5247 err_code |= ERR_ALERT | ERR_FATAL;
5248 goto out;
5249 }
5250 tcpcheck->comment = strdup(args[4]);
5251 }
5252
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005253 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5254 }
5255 }
5256 else if (strcmp(args[1], "send-binary") == 0) {
5257 if (! *(args[2]) ) {
5258 /* SEND binary string expected */
5259 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
5260 file, linenum, args[0], args[1], args[2]);
5261 err_code |= ERR_ALERT | ERR_FATAL;
5262 goto out;
5263 } else {
5264 struct tcpcheck_rule *tcpcheck;
5265 char *err = NULL;
5266
5267 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5268
5269 tcpcheck->action = TCPCHK_ACT_SEND;
5270 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5271 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5272 file, linenum, args[0], args[1], args[2], err);
5273 err_code |= ERR_ALERT | ERR_FATAL;
5274 goto out;
5275 }
5276 tcpcheck->expect_regex = NULL;
5277
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005278 /* comment for this tcpcheck line */
5279 if (strcmp(args[3], "comment") == 0) {
5280 if (!*args[4]) {
5281 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5282 file, linenum, args[3]);
5283 err_code |= ERR_ALERT | ERR_FATAL;
5284 goto out;
5285 }
5286 tcpcheck->comment = strdup(args[4]);
5287 }
5288
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005289 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5290 }
5291 }
5292 else if (strcmp(args[1], "expect") == 0) {
5293 const char *ptr_arg;
5294 int cur_arg;
5295 int inverse = 0;
5296
5297 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5298 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5299 err_code |= ERR_ALERT | ERR_FATAL;
5300 goto out;
5301 }
5302
5303 cur_arg = 2;
5304 /* consider exclamation marks, sole or at the beginning of a word */
5305 while (*(ptr_arg = args[cur_arg])) {
5306 while (*ptr_arg == '!') {
5307 inverse = !inverse;
5308 ptr_arg++;
5309 }
5310 if (*ptr_arg)
5311 break;
5312 cur_arg++;
5313 }
5314 /* now ptr_arg points to the beginning of a word past any possible
5315 * exclamation mark, and cur_arg is the argument which holds this word.
5316 */
5317 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005318 struct tcpcheck_rule *tcpcheck;
5319 char *err = NULL;
5320
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005321 if (!*(args[cur_arg + 1])) {
5322 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
5323 file, linenum, args[0], args[1], ptr_arg);
5324 err_code |= ERR_ALERT | ERR_FATAL;
5325 goto out;
5326 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005327
5328 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5329
5330 tcpcheck->action = TCPCHK_ACT_EXPECT;
5331 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5332 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5333 file, linenum, args[0], args[1], args[2], err);
5334 err_code |= ERR_ALERT | ERR_FATAL;
5335 goto out;
5336 }
5337 tcpcheck->expect_regex = NULL;
5338 tcpcheck->inverse = inverse;
5339
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005340 /* tcpcheck comment */
5341 cur_arg += 2;
5342 if (strcmp(args[cur_arg], "comment") == 0) {
5343 if (!*args[cur_arg + 1]) {
5344 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5345 file, linenum, args[cur_arg + 1]);
5346 err_code |= ERR_ALERT | ERR_FATAL;
5347 goto out;
5348 }
5349 tcpcheck->comment = strdup(args[cur_arg + 1]);
5350 }
5351
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005352 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5353 }
5354 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005355 struct tcpcheck_rule *tcpcheck;
5356
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005357 if (!*(args[cur_arg + 1])) {
5358 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5359 file, linenum, args[0], args[1], ptr_arg);
5360 err_code |= ERR_ALERT | ERR_FATAL;
5361 goto out;
5362 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005363
5364 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5365
5366 tcpcheck->action = TCPCHK_ACT_EXPECT;
5367 tcpcheck->string_len = strlen(args[cur_arg + 1]);
5368 tcpcheck->string = strdup(args[cur_arg + 1]);
5369 tcpcheck->expect_regex = NULL;
5370 tcpcheck->inverse = inverse;
5371
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005372 /* tcpcheck comment */
5373 cur_arg += 2;
5374 if (strcmp(args[cur_arg], "comment") == 0) {
5375 if (!*args[cur_arg + 1]) {
5376 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5377 file, linenum, args[cur_arg + 1]);
5378 err_code |= ERR_ALERT | ERR_FATAL;
5379 goto out;
5380 }
5381 tcpcheck->comment = strdup(args[cur_arg + 1]);
5382 }
5383
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005384 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5385 }
5386 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005387 struct tcpcheck_rule *tcpcheck;
5388
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005389 if (!*(args[cur_arg + 1])) {
5390 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5391 file, linenum, args[0], args[1], ptr_arg);
5392 err_code |= ERR_ALERT | ERR_FATAL;
5393 goto out;
5394 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005395
5396 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5397
5398 tcpcheck->action = TCPCHK_ACT_EXPECT;
5399 tcpcheck->string_len = 0;
5400 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005401 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
5402 error = NULL;
5403 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
5404 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5405 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5406 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005407 err_code |= ERR_ALERT | ERR_FATAL;
5408 goto out;
5409 }
5410 tcpcheck->inverse = inverse;
5411
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005412 /* tcpcheck comment */
5413 cur_arg += 2;
5414 if (strcmp(args[cur_arg], "comment") == 0) {
5415 if (!*args[cur_arg + 1]) {
5416 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5417 file, linenum, args[cur_arg + 1]);
5418 err_code |= ERR_ALERT | ERR_FATAL;
5419 goto out;
5420 }
5421 tcpcheck->comment = strdup(args[cur_arg + 1]);
5422 }
5423
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005424 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5425 }
5426 else {
5427 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
5428 file, linenum, args[0], args[1], ptr_arg);
5429 err_code |= ERR_ALERT | ERR_FATAL;
5430 goto out;
5431 }
5432 }
5433 else {
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005434 Alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005435 err_code |= ERR_ALERT | ERR_FATAL;
5436 goto out;
5437 }
5438 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01005439 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02005440 if (curproxy == &defproxy) {
5441 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005442 err_code |= ERR_ALERT | ERR_FATAL;
5443 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02005444 }
5445
Willy Tarreaub80c2302007-11-30 20:51:32 +01005446 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005447 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005448
5449 if (strcmp(args[1], "fail") == 0) {
5450 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01005451 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01005452 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
5453 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005454 err_code |= ERR_ALERT | ERR_FATAL;
5455 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005456 }
5457
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005458 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
5459 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
5460 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005461 err_code |= ERR_ALERT | ERR_FATAL;
5462 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005463 }
5464 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
5465 }
5466 else {
5467 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005468 err_code |= ERR_ALERT | ERR_FATAL;
5469 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005470 }
5471 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005472#ifdef TPROXY
5473 else if (!strcmp(args[0], "transparent")) {
5474 /* enable transparent proxy connections */
5475 curproxy->options |= PR_O_TRANSP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005476 if (alertif_too_many_args(0, file, linenum, args, &err_code))
5477 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005478 }
5479#endif
5480 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005481 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005482 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005483
Willy Tarreaubaaee002006-06-26 02:48:02 +02005484 if (*(args[1]) == 0) {
5485 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005486 err_code |= ERR_ALERT | ERR_FATAL;
5487 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005488 }
5489 curproxy->maxconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005490 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5491 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005492 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005493 else if (!strcmp(args[0], "backlog")) { /* backlog */
5494 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005495 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005496
5497 if (*(args[1]) == 0) {
5498 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005499 err_code |= ERR_ALERT | ERR_FATAL;
5500 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005501 }
5502 curproxy->backlog = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005503 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5504 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005505 }
Willy Tarreau86034312006-12-29 00:10:33 +01005506 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005507 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005508 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005509
Willy Tarreau86034312006-12-29 00:10:33 +01005510 if (*(args[1]) == 0) {
5511 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005512 err_code |= ERR_ALERT | ERR_FATAL;
5513 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005514 }
5515 curproxy->fullconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005516 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5517 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005518 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005519 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
5520 if (*(args[1]) == 0) {
5521 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005522 err_code |= ERR_ALERT | ERR_FATAL;
5523 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005524 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005525 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
5526 if (err) {
5527 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
5528 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02005529 err_code |= ERR_ALERT | ERR_FATAL;
5530 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005531 }
5532 curproxy->grace = val;
William Lallemanddf1425a2015-04-28 20:17:49 +02005533 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5534 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005535 }
5536 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01005537 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005538 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005539 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005540
Willy Tarreaubaaee002006-06-26 02:48:02 +02005541 if (curproxy == &defproxy) {
5542 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005543 err_code |= ERR_ALERT | ERR_FATAL;
5544 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005545 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005546 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005547 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005548
Willy Tarreau72b8c1f2015-09-08 15:50:19 +02005549 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005550 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005551 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005552 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005553 goto out;
5554 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005555
5556 proto = protocol_by_family(sk->ss_family);
5557 if (!proto || !proto->connect) {
5558 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5559 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005560 err_code |= ERR_ALERT | ERR_FATAL;
5561 goto out;
5562 }
5563
5564 if (port1 != port2) {
5565 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5566 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005567 err_code |= ERR_ALERT | ERR_FATAL;
5568 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005569 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005570
5571 if (!port1) {
5572 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5573 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005574 err_code |= ERR_ALERT | ERR_FATAL;
5575 goto out;
5576 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005577
William Lallemanddf1425a2015-04-28 20:17:49 +02005578 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5579 goto out;
5580
Willy Tarreaud5191e72010-02-09 20:50:45 +01005581 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005582 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005583 }
5584 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005585 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005586 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005587
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005588 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5589 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005590 err_code |= ERR_ALERT | ERR_FATAL;
5591 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005592 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005593 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005594 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005595 /**
5596 * The syntax for hash-type config element is
5597 * hash-type {map-based|consistent} [[<algo>] avalanche]
5598 *
5599 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5600 */
5601 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005602
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005603 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5604 err_code |= ERR_WARN;
5605
5606 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005607 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5608 }
5609 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005610 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5611 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005612 else if (strcmp(args[1], "avalanche") == 0) {
5613 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]);
5614 err_code |= ERR_ALERT | ERR_FATAL;
5615 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005616 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005617 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005618 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005619 err_code |= ERR_ALERT | ERR_FATAL;
5620 goto out;
5621 }
Bhaskar98634f02013-10-29 23:30:51 -04005622
5623 /* set the hash function to use */
5624 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005625 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005626 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005627
5628 /* if consistent with no argument, then avalanche modifier is also applied */
5629 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5630 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005631 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005632 /* set the hash function */
5633 if (!strcmp(args[2], "sdbm")) {
5634 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5635 }
5636 else if (!strcmp(args[2], "djb2")) {
5637 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005638 }
5639 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005640 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005641 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005642 else if (!strcmp(args[2], "crc32")) {
5643 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5644 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005645 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005646 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 -05005647 err_code |= ERR_ALERT | ERR_FATAL;
5648 goto out;
5649 }
5650
5651 /* set the hash modifier */
5652 if (!strcmp(args[3], "avalanche")) {
5653 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5654 }
5655 else if (*args[3]) {
5656 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5657 err_code |= ERR_ALERT | ERR_FATAL;
5658 goto out;
5659 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005660 }
William Lallemanda73203e2012-03-12 12:48:57 +01005661 }
William Lallemanda73203e2012-03-12 12:48:57 +01005662 else if (strcmp(args[0], "unique-id-format") == 0) {
5663 if (!*(args[1])) {
5664 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5665 err_code |= ERR_ALERT | ERR_FATAL;
5666 goto out;
5667 }
William Lallemand3203ff42012-11-11 17:30:56 +01005668 if (*(args[2])) {
5669 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5670 err_code |= ERR_ALERT | ERR_FATAL;
5671 goto out;
5672 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005673 free(curproxy->conf.uniqueid_format_string);
5674 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005675
Willy Tarreau62a61232013-04-12 18:13:46 +02005676 free(curproxy->conf.uif_file);
5677 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5678 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005679 }
William Lallemanda73203e2012-03-12 12:48:57 +01005680
5681 else if (strcmp(args[0], "unique-id-header") == 0) {
5682 if (!*(args[1])) {
5683 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5684 err_code |= ERR_ALERT | ERR_FATAL;
5685 goto out;
5686 }
5687 free(curproxy->header_unique_id);
5688 curproxy->header_unique_id = strdup(args[1]);
5689 }
5690
William Lallemand723b73a2012-02-08 16:37:49 +01005691 else if (strcmp(args[0], "log-format") == 0) {
5692 if (!*(args[1])) {
5693 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5694 err_code |= ERR_ALERT | ERR_FATAL;
5695 goto out;
5696 }
William Lallemand3203ff42012-11-11 17:30:56 +01005697 if (*(args[2])) {
5698 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5699 err_code |= ERR_ALERT | ERR_FATAL;
5700 goto out;
5701 }
Willy Tarreau196729e2012-05-31 19:30:26 +02005702
Willy Tarreau62a61232013-04-12 18:13:46 +02005703 if (curproxy->conf.logformat_string != default_http_log_format &&
5704 curproxy->conf.logformat_string != default_tcp_log_format &&
5705 curproxy->conf.logformat_string != clf_http_log_format)
5706 free(curproxy->conf.logformat_string);
5707 curproxy->conf.logformat_string = strdup(args[1]);
5708
5709 free(curproxy->conf.lfs_file);
5710 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5711 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005712
5713 /* get a chance to improve log-format error reporting by
5714 * reporting the correct line-number when possible.
5715 */
5716 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5717 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5718 file, linenum, curproxy->id);
5719 err_code |= ERR_WARN;
5720 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005721 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01005722 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
5723 if (*(args[1]) == 0) {
5724 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
5725 err_code |= ERR_ALERT | ERR_FATAL;
5726 goto out;
5727 }
5728 free(curproxy->log_tag);
5729 curproxy->log_tag = strdup(args[1]);
5730 }
William Lallemand0f99e342011-10-12 17:50:54 +02005731 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
5732 /* delete previous herited or defined syslog servers */
5733 struct logsrv *back;
5734
5735 if (*(args[1]) != 0) {
5736 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
5737 err_code |= ERR_ALERT | ERR_FATAL;
5738 goto out;
5739 }
5740
William Lallemand723b73a2012-02-08 16:37:49 +01005741 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
5742 LIST_DEL(&tmplogsrv->list);
5743 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02005744 }
5745 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005746 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02005747 struct logsrv *logsrv;
5748
Willy Tarreaubaaee002006-06-26 02:48:02 +02005749 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005750 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01005751 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02005752 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01005753 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02005754 LIST_INIT(&node->list);
5755 LIST_ADDQ(&curproxy->logsrvs, &node->list);
5756 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005757 }
5758 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005759 struct sockaddr_storage *sk;
5760 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02005761 int arg = 0;
5762 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02005763
5764 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005765
Willy Tarreau18324f52014-06-27 18:10:07 +02005766 /* just after the address, a length may be specified */
5767 if (strcmp(args[arg+2], "len") == 0) {
5768 len = atoi(args[arg+3]);
5769 if (len < 80 || len > 65535) {
5770 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
5771 file, linenum, args[arg+3]);
5772 err_code |= ERR_ALERT | ERR_FATAL;
5773 goto out;
5774 }
5775 logsrv->maxlen = len;
5776
5777 /* skip these two args */
5778 arg += 2;
5779 }
5780 else
5781 logsrv->maxlen = MAX_SYSLOG_LEN;
5782
5783 if (logsrv->maxlen > global.max_syslog_len) {
5784 global.max_syslog_len = logsrv->maxlen;
5785 logline = realloc(logline, global.max_syslog_len + 1);
5786 }
5787
William Lallemanddf1425a2015-04-28 20:17:49 +02005788 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
5789 goto out;
5790
Willy Tarreau18324f52014-06-27 18:10:07 +02005791 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005792 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005793 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005794 err_code |= ERR_ALERT | ERR_FATAL;
5795 goto out;
5796
Willy Tarreaubaaee002006-06-26 02:48:02 +02005797 }
5798
William Lallemand0f99e342011-10-12 17:50:54 +02005799 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02005800 if (*(args[arg+3])) {
5801 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005802 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005803 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005804 err_code |= ERR_ALERT | ERR_FATAL;
5805 goto out;
5806
Willy Tarreaubaaee002006-06-26 02:48:02 +02005807 }
5808 }
5809
William Lallemand0f99e342011-10-12 17:50:54 +02005810 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02005811 if (*(args[arg+4])) {
5812 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01005813 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005814 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02005815 err_code |= ERR_ALERT | ERR_FATAL;
5816 goto out;
5817
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005818 }
5819 }
5820
Willy Tarreau72b8c1f2015-09-08 15:50:19 +02005821 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005822 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005823 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005824 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005825 goto out;
5826 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005827
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005828 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005829
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005830 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005831 if (port1 != port2) {
5832 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5833 file, linenum, args[0], args[1]);
5834 err_code |= ERR_ALERT | ERR_FATAL;
5835 goto out;
5836 }
5837
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005838 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02005839 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005840 }
William Lallemand0f99e342011-10-12 17:50:54 +02005841
5842 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005843 }
5844 else {
5845 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
5846 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005847 err_code |= ERR_ALERT | ERR_FATAL;
5848 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005849 }
5850 }
5851 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005852 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005853 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01005854 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005855 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005856
Willy Tarreau977b8e42006-12-29 14:19:17 +01005857 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005858 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005859
Willy Tarreaubaaee002006-06-26 02:48:02 +02005860 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005861 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
5862 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005863 err_code |= ERR_ALERT | ERR_FATAL;
5864 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005865 }
Willy Tarreau368480c2009-03-01 08:27:21 +01005866
5867 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01005868 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5869 free(curproxy->conn_src.iface_name);
5870 curproxy->conn_src.iface_name = NULL;
5871 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01005872
Willy Tarreau72b8c1f2015-09-08 15:50:19 +02005873 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005874 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005875 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005876 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005877 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005878 goto out;
5879 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005880
5881 proto = protocol_by_family(sk->ss_family);
5882 if (!proto || !proto->connect) {
5883 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005884 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005885 err_code |= ERR_ALERT | ERR_FATAL;
5886 goto out;
5887 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005888
5889 if (port1 != port2) {
5890 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5891 file, linenum, args[0], args[1]);
5892 err_code |= ERR_ALERT | ERR_FATAL;
5893 goto out;
5894 }
5895
Willy Tarreauef9a3602012-12-08 22:29:20 +01005896 curproxy->conn_src.source_addr = *sk;
5897 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005898
5899 cur_arg = 2;
5900 while (*(args[cur_arg])) {
5901 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau29fbe512015-08-20 19:35:14 +02005902#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005903 if (!*args[cur_arg + 1]) {
5904 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5905 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005906 err_code |= ERR_ALERT | ERR_FATAL;
5907 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005908 }
5909
5910 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005911 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5912 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005913 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005914 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5915 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005916 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5917 char *name, *end;
5918
5919 name = args[cur_arg+1] + 7;
5920 while (isspace(*name))
5921 name++;
5922
5923 end = name;
5924 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5925 end++;
5926
Willy Tarreauef9a3602012-12-08 22:29:20 +01005927 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5928 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5929 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5930 curproxy->conn_src.bind_hdr_len = end - name;
5931 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5932 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5933 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005934
5935 /* now look for an occurrence number */
5936 while (isspace(*end))
5937 end++;
5938 if (*end == ',') {
5939 end++;
5940 name = end;
5941 if (*end == '-')
5942 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005943 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005944 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005945 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005946 }
5947
Willy Tarreauef9a3602012-12-08 22:29:20 +01005948 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005949 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5950 " occurrences values smaller than %d.\n",
5951 file, linenum, MAX_HDR_HISTORY);
5952 err_code |= ERR_ALERT | ERR_FATAL;
5953 goto out;
5954 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005955 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005956 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005957
Willy Tarreau72b8c1f2015-09-08 15:50:19 +02005958 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005959 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005960 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005961 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005962 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005963 goto out;
5964 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005965
5966 proto = protocol_by_family(sk->ss_family);
5967 if (!proto || !proto->connect) {
5968 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5969 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005970 err_code |= ERR_ALERT | ERR_FATAL;
5971 goto out;
5972 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005973
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[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005977 err_code |= ERR_ALERT | ERR_FATAL;
5978 goto out;
5979 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005980 curproxy->conn_src.tproxy_addr = *sk;
5981 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005982 }
5983 global.last_checks |= LSTCHK_NETADM;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005984#else /* no TPROXY support */
5985 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005986 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005987 err_code |= ERR_ALERT | ERR_FATAL;
5988 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005989#endif
5990 cur_arg += 2;
5991 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005992 }
5993
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005994 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5995#ifdef SO_BINDTODEVICE
5996 if (!*args[cur_arg + 1]) {
5997 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5998 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005999 err_code |= ERR_ALERT | ERR_FATAL;
6000 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006001 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006002 free(curproxy->conn_src.iface_name);
6003 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
6004 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006005 global.last_checks |= LSTCHK_NETADM;
6006#else
6007 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
6008 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02006009 err_code |= ERR_ALERT | ERR_FATAL;
6010 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01006011#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006012 cur_arg += 2;
6013 continue;
6014 }
6015 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02006016 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006017 err_code |= ERR_ALERT | ERR_FATAL;
6018 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006019 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006020 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006021 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
6022 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
6023 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02006024 err_code |= ERR_ALERT | ERR_FATAL;
6025 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006026 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006027 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006028 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006029 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6030 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006031 err_code |= ERR_ALERT | ERR_FATAL;
6032 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006033 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006034
6035 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006036 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006037 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006038 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006039 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006040 }
6041 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006042 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006043 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006044 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006045 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006046 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006047 }
6048 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006049 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006050 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006051 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006052 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006053 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006054 }
6055 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006056 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006057 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006058 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006059 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006060 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006061 }
6062 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006063 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006064 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006065 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006066 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006067 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006068 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006069 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006070 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006071 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006072 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006073 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006074 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006075 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006076 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006077 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006078 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6079 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006080 err_code |= ERR_ALERT | ERR_FATAL;
6081 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006082 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006083
6084 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006085 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006086 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006087 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006088 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006089 }
6090 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006091 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006092 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006093 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006094 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006095 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006096 }
6097 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006098 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006099 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006100 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006101 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006102 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006103 }
6104 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006105 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006106 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006107 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006108 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006109 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006110 }
6111 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006112 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006113 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006114 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006115 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006116 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006117 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006118 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006119 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006120 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006121 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006122 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006123 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006124 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006125 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006126 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006127
Willy Tarreaubaaee002006-06-26 02:48:02 +02006128 if (curproxy == &defproxy) {
6129 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006130 err_code |= ERR_ALERT | ERR_FATAL;
6131 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006132 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006133 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006134 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006135
Willy Tarreaubaaee002006-06-26 02:48:02 +02006136 if (*(args[1]) == 0) {
6137 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006138 err_code |= ERR_ALERT | ERR_FATAL;
6139 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006140 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006141
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006142 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006143 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6144 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6145 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006146 err_code |= ERR_ALERT | ERR_FATAL;
6147 goto out;
6148 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006149 err_code |= warnif_cond_conflicts(cond,
6150 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6151 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006152 }
6153 else if (*args[2]) {
6154 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6155 file, linenum, args[0], args[2]);
6156 err_code |= ERR_ALERT | ERR_FATAL;
6157 goto out;
6158 }
6159
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006160 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006161 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006162 wl->s = strdup(args[1]);
6163 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02006164 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006165 }
6166 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006167 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006168 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6169 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006170 err_code |= ERR_ALERT | ERR_FATAL;
6171 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006172 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006173
Willy Tarreauade5ec42010-01-28 19:33:49 +01006174 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006175 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006176 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006177 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006178 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006179 }
6180 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006181 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006182 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006183 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006184 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006185 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006186 }
6187 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006188 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006189 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006190 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006191 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006192 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006193 }
6194 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006195 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006196 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6197 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006198 err_code |= ERR_ALERT | ERR_FATAL;
6199 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006200 }
6201
Willy Tarreauade5ec42010-01-28 19:33:49 +01006202 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006203 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006204 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006205 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006206 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006207 }
6208 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006209 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006210 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006211 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006212 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006213 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006214 }
6215 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006216 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006217 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006218 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006219 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006220 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006221 }
6222 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006223 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006224
Willy Tarreaubaaee002006-06-26 02:48:02 +02006225 if (curproxy == &defproxy) {
6226 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006227 err_code |= ERR_ALERT | ERR_FATAL;
6228 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006229 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006230 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006231 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006232
Willy Tarreaubaaee002006-06-26 02:48:02 +02006233 if (*(args[1]) == 0) {
6234 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006235 err_code |= ERR_ALERT | ERR_FATAL;
6236 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006237 }
6238
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006239 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006240 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6241 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6242 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006243 err_code |= ERR_ALERT | ERR_FATAL;
6244 goto out;
6245 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006246 err_code |= warnif_cond_conflicts(cond,
6247 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
6248 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006249 }
6250 else if (*args[2]) {
6251 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6252 file, linenum, args[0], args[2]);
6253 err_code |= ERR_ALERT | ERR_FATAL;
6254 goto out;
6255 }
6256
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006257 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006258 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006259 wl->s = strdup(args[1]);
6260 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006261 }
6262 else if (!strcmp(args[0], "errorloc") ||
6263 !strcmp(args[0], "errorloc302") ||
6264 !strcmp(args[0], "errorloc303")) { /* error location */
6265 int errnum, errlen;
6266 char *err;
6267
Willy Tarreau977b8e42006-12-29 14:19:17 +01006268 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006269 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006270
Willy Tarreaubaaee002006-06-26 02:48:02 +02006271 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006272 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\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 }
6276
6277 errnum = atol(args[1]);
6278 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006279 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
6280 err = malloc(errlen);
6281 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006282 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006283 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
6284 err = malloc(errlen);
6285 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006286 }
6287
Willy Tarreau0f772532006-12-23 20:51:41 +01006288 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6289 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006290 chunk_destroy(&curproxy->errmsg[rc]);
6291 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01006292 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006293 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006294 }
Willy Tarreau0f772532006-12-23 20:51:41 +01006295
6296 if (rc >= HTTP_ERR_SIZE) {
6297 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
6298 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006299 free(err);
6300 }
6301 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02006302 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
6303 int errnum, errlen, fd;
6304 char *err;
6305 struct stat stat;
6306
6307 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006308 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006309
6310 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006311 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006312 err_code |= ERR_ALERT | ERR_FATAL;
6313 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006314 }
6315
6316 fd = open(args[2], O_RDONLY);
6317 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
6318 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
6319 file, linenum, args[2], args[1]);
6320 if (fd >= 0)
6321 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02006322 err_code |= ERR_ALERT | ERR_FATAL;
6323 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006324 }
6325
Willy Tarreau27a674e2009-08-17 07:23:33 +02006326 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02006327 errlen = stat.st_size;
6328 } else {
6329 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02006330 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02006331 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02006332 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006333 }
6334
6335 err = malloc(errlen); /* malloc() must succeed during parsing */
6336 errnum = read(fd, err, errlen);
6337 if (errnum != errlen) {
6338 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
6339 file, linenum, args[2], args[1]);
6340 close(fd);
6341 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02006342 err_code |= ERR_ALERT | ERR_FATAL;
6343 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006344 }
6345 close(fd);
6346
6347 errnum = atol(args[1]);
6348 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6349 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006350 chunk_destroy(&curproxy->errmsg[rc]);
6351 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02006352 break;
6353 }
6354 }
6355
6356 if (rc >= HTTP_ERR_SIZE) {
6357 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
6358 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02006359 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006360 free(err);
6361 }
6362 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006363 else if (!strcmp(args[0], "compression")) {
6364 struct comp *comp;
6365 if (curproxy->comp == NULL) {
6366 comp = calloc(1, sizeof(struct comp));
6367 curproxy->comp = comp;
6368 } else {
6369 comp = curproxy->comp;
6370 }
6371
6372 if (!strcmp(args[1], "algo")) {
6373 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01006374 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01006375
William Lallemand82fe75c2012-10-23 10:25:10 +02006376 cur_arg = 2;
6377 if (!*args[cur_arg]) {
6378 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
6379 file, linenum, args[0]);
6380 err_code |= ERR_ALERT | ERR_FATAL;
6381 goto out;
6382 }
6383 while (*(args[cur_arg])) {
6384 if (comp_append_algo(comp, args[cur_arg]) < 0) {
6385 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
6386 file, linenum, args[0], args[cur_arg]);
6387 err_code |= ERR_ALERT | ERR_FATAL;
6388 goto out;
6389 }
William Lallemand552df672012-11-07 13:21:47 +01006390 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
6391 curproxy->comp->algos->end(&ctx);
6392 } else {
6393 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
6394 file, linenum, args[0], args[cur_arg]);
6395 err_code |= ERR_ALERT | ERR_FATAL;
6396 goto out;
6397 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006398 cur_arg ++;
6399 continue;
6400 }
6401 }
Willy Tarreau70737d12012-10-27 00:34:28 +02006402 else if (!strcmp(args[1], "offload")) {
6403 comp->offload = 1;
6404 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006405 else if (!strcmp(args[1], "type")) {
6406 int cur_arg;
6407 cur_arg = 2;
6408 if (!*args[cur_arg]) {
6409 Alert("parsing [%s:%d] : '%s' expects <type>\n",
6410 file, linenum, args[0]);
6411 err_code |= ERR_ALERT | ERR_FATAL;
6412 goto out;
6413 }
6414 while (*(args[cur_arg])) {
6415 comp_append_type(comp, args[cur_arg]);
6416 cur_arg ++;
6417 continue;
6418 }
6419 }
6420 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02006421 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02006422 file, linenum, args[0]);
6423 err_code |= ERR_ALERT | ERR_FATAL;
6424 goto out;
6425 }
6426 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006427 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006428 struct cfg_kw_list *kwl;
6429 int index;
6430
6431 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6432 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6433 if (kwl->kw[index].section != CFG_LISTEN)
6434 continue;
6435 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6436 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006437 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006438 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006439 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006440 err_code |= ERR_ALERT | ERR_FATAL;
6441 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006442 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006443 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006444 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006445 err_code |= ERR_WARN;
6446 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006447 }
Willy Tarreau93893792009-07-23 13:19:11 +02006448 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006449 }
6450 }
6451 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006452
Willy Tarreau6daf3432008-01-22 16:44:08 +01006453 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006454 err_code |= ERR_ALERT | ERR_FATAL;
6455 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006456 }
Willy Tarreau93893792009-07-23 13:19:11 +02006457 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006458 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006459 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006460}
6461
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006462int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006463cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
6464{
6465#ifdef CONFIG_HAP_NS
6466 const char *err;
6467 const char *item = args[0];
6468
6469 if (!strcmp(item, "namespace_list")) {
6470 return 0;
6471 }
6472 else if (!strcmp(item, "namespace")) {
6473 size_t idx = 1;
6474 const char *current;
6475 while (*(current = args[idx++])) {
6476 err = invalid_char(current);
6477 if (err) {
6478 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6479 file, linenum, *err, item, current);
6480 return ERR_ALERT | ERR_FATAL;
6481 }
6482
6483 if (netns_store_lookup(current, strlen(current))) {
6484 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
6485 file, linenum, current);
6486 return ERR_ALERT | ERR_FATAL;
6487 }
6488 if (!netns_store_insert(current)) {
6489 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
6490 file, linenum, current);
6491 return ERR_ALERT | ERR_FATAL;
6492 }
6493 }
6494 }
6495
6496 return 0;
6497#else
6498 Alert("parsing [%s:%d]: namespace support is not compiled in.",
6499 file, linenum);
6500 return ERR_ALERT | ERR_FATAL;
6501#endif
6502}
6503
6504int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006505cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6506{
6507
6508 int err_code = 0;
6509 const char *err;
6510
6511 if (!strcmp(args[0], "userlist")) { /* new userlist */
6512 struct userlist *newul;
6513
6514 if (!*args[1]) {
6515 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6516 file, linenum, args[0]);
6517 err_code |= ERR_ALERT | ERR_FATAL;
6518 goto out;
6519 }
William Lallemand6e62fb62015-04-28 16:55:23 +02006520 if (alertif_too_many_args(1, file, linenum, args, &err_code))
6521 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006522
6523 err = invalid_char(args[1]);
6524 if (err) {
6525 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6526 file, linenum, *err, args[0], args[1]);
6527 err_code |= ERR_ALERT | ERR_FATAL;
6528 goto out;
6529 }
6530
6531 for (newul = userlist; newul; newul = newul->next)
6532 if (!strcmp(newul->name, args[1])) {
6533 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6534 file, linenum, args[1]);
6535 err_code |= ERR_WARN;
6536 goto out;
6537 }
6538
6539 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
6540 if (!newul) {
6541 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6542 err_code |= ERR_ALERT | ERR_ABORT;
6543 goto out;
6544 }
6545
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006546 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006547 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006548 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6549 err_code |= ERR_ALERT | ERR_ABORT;
6550 goto out;
6551 }
6552
6553 newul->next = userlist;
6554 userlist = newul;
6555
6556 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006557 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006558 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006559 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006560
6561 if (!*args[1]) {
6562 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6563 file, linenum, args[0]);
6564 err_code |= ERR_ALERT | ERR_FATAL;
6565 goto out;
6566 }
6567
6568 err = invalid_char(args[1]);
6569 if (err) {
6570 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6571 file, linenum, *err, args[0], args[1]);
6572 err_code |= ERR_ALERT | ERR_FATAL;
6573 goto out;
6574 }
6575
William Lallemand4ac9f542015-05-28 18:03:51 +02006576 if (!userlist)
6577 goto out;
6578
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006579 for (ag = userlist->groups; ag; ag = ag->next)
6580 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006581 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6582 file, linenum, args[1], userlist->name);
6583 err_code |= ERR_ALERT;
6584 goto out;
6585 }
6586
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006587 ag = calloc(1, sizeof(*ag));
6588 if (!ag) {
6589 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6590 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006591 goto out;
6592 }
6593
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006594 ag->name = strdup(args[1]);
6595 if (!ag) {
6596 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6597 err_code |= ERR_ALERT | ERR_ABORT;
6598 goto out;
6599 }
6600
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006601 cur_arg = 2;
6602
6603 while (*args[cur_arg]) {
6604 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006605 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006606 cur_arg += 2;
6607 continue;
6608 } else {
6609 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6610 file, linenum, args[0]);
6611 err_code |= ERR_ALERT | ERR_FATAL;
6612 goto out;
6613 }
6614 }
6615
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006616 ag->next = userlist->groups;
6617 userlist->groups = ag;
6618
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006619 } else if (!strcmp(args[0], "user")) { /* new user */
6620 struct auth_users *newuser;
6621 int cur_arg;
6622
6623 if (!*args[1]) {
6624 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6625 file, linenum, args[0]);
6626 err_code |= ERR_ALERT | ERR_FATAL;
6627 goto out;
6628 }
William Lallemand4ac9f542015-05-28 18:03:51 +02006629 if (!userlist)
6630 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006631
6632 for (newuser = userlist->users; newuser; newuser = newuser->next)
6633 if (!strcmp(newuser->user, args[1])) {
6634 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6635 file, linenum, args[1], userlist->name);
6636 err_code |= ERR_ALERT;
6637 goto out;
6638 }
6639
6640 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
6641 if (!newuser) {
6642 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6643 err_code |= ERR_ALERT | ERR_ABORT;
6644 goto out;
6645 }
6646
6647 newuser->user = strdup(args[1]);
6648
6649 newuser->next = userlist->users;
6650 userlist->users = newuser;
6651
6652 cur_arg = 2;
6653
6654 while (*args[cur_arg]) {
6655 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006656#ifdef CONFIG_HAP_CRYPT
6657 if (!crypt("", args[cur_arg + 1])) {
6658 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6659 file, linenum, newuser->user);
6660 err_code |= ERR_ALERT | ERR_FATAL;
6661 goto out;
6662 }
6663#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006664 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6665 file, linenum);
6666 err_code |= ERR_ALERT;
6667#endif
6668 newuser->pass = strdup(args[cur_arg + 1]);
6669 cur_arg += 2;
6670 continue;
6671 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6672 newuser->pass = strdup(args[cur_arg + 1]);
6673 newuser->flags |= AU_O_INSECURE;
6674 cur_arg += 2;
6675 continue;
6676 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006677 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006678 cur_arg += 2;
6679 continue;
6680 } else {
6681 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6682 file, linenum, args[0]);
6683 err_code |= ERR_ALERT | ERR_FATAL;
6684 goto out;
6685 }
6686 }
6687 } else {
6688 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6689 err_code |= ERR_ALERT | ERR_FATAL;
6690 }
6691
6692out:
6693 return err_code;
6694}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006695
6696/*
6697 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006698 * Returns the error code, 0 if OK, or any combination of :
6699 * - ERR_ABORT: must abort ASAP
6700 * - ERR_FATAL: we can continue parsing but not start the service
6701 * - ERR_WARN: a warning has been emitted
6702 * - ERR_ALERT: an alert has been emitted
6703 * Only the two first ones can stop processing, the two others are just
6704 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006705 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006706int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006707{
William Lallemand64e84512015-05-12 14:25:37 +02006708 char *thisline;
6709 int linesize = LINESIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006710 FILE *f;
6711 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02006712 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006713 struct cfg_section *cs = NULL;
6714 struct cfg_section *ics;
William Lallemand64e84512015-05-12 14:25:37 +02006715 int readbytes = 0;
6716
6717 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
William Lallemandb2f07452015-05-12 14:27:13 +02006718 Alert("parsing [%s] : out of memory.\n", file);
William Lallemand64e84512015-05-12 14:25:37 +02006719 return -1;
6720 }
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006721
6722 /* Register internal sections */
6723 if (!cfg_register_section("listen", cfg_parse_listen) ||
6724 !cfg_register_section("frontend", cfg_parse_listen) ||
6725 !cfg_register_section("backend", cfg_parse_listen) ||
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006726 !cfg_register_section("defaults", cfg_parse_listen) ||
6727 !cfg_register_section("global", cfg_parse_global) ||
6728 !cfg_register_section("userlist", cfg_parse_users) ||
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006729 !cfg_register_section("peers", cfg_parse_peers) ||
Simon Horman0d16a402015-01-30 11:22:58 +09006730 !cfg_register_section("mailers", cfg_parse_mailers) ||
Baptiste Assmann325137d2015-04-13 23:40:55 +02006731 !cfg_register_section("namespace_list", cfg_parse_netns) ||
6732 !cfg_register_section("resolvers", cfg_parse_resolvers))
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006733 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006734
Willy Tarreaubaaee002006-06-26 02:48:02 +02006735 if ((f=fopen(file,"r")) == NULL)
6736 return -1;
6737
William Lallemandb2f07452015-05-12 14:27:13 +02006738next_line:
William Lallemand64e84512015-05-12 14:25:37 +02006739 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02006740 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006741 char *end;
6742 char *args[MAX_LINE_ARGS + 1];
6743 char *line = thisline;
William Lallemandf9873ba2015-05-05 17:37:14 +02006744 int dquote = 0; /* double quote */
6745 int squote = 0; /* simple quote */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006746
Willy Tarreaubaaee002006-06-26 02:48:02 +02006747 linenum++;
6748
6749 end = line + strlen(line);
6750
William Lallemand64e84512015-05-12 14:25:37 +02006751 if (end-line == linesize-1 && *(end-1) != '\n') {
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006752 /* Check if we reached the limit and the last char is not \n.
6753 * Watch out for the last line without the terminating '\n'!
6754 */
William Lallemand64e84512015-05-12 14:25:37 +02006755 char *newline;
6756 int newlinesize = linesize * 2;
6757
6758 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
6759 if (newline == NULL) {
6760 Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
6761 file, linenum);
6762 err_code |= ERR_ALERT | ERR_FATAL;
6763 continue;
6764 }
6765
6766 readbytes = linesize - 1;
6767 linesize = newlinesize;
6768 thisline = newline;
6769 continue;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006770 }
6771
William Lallemand64e84512015-05-12 14:25:37 +02006772 readbytes = 0;
6773
Willy Tarreaubaaee002006-06-26 02:48:02 +02006774 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006775 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006776 line++;
William Lallemandf9873ba2015-05-05 17:37:14 +02006777
Willy Tarreaubaaee002006-06-26 02:48:02 +02006778 arg = 0;
6779 args[arg] = line;
6780
6781 while (*line && arg < MAX_LINE_ARGS) {
William Lallemandf9873ba2015-05-05 17:37:14 +02006782 if (*line == '"' && !squote) { /* double quote outside single quotes */
6783 if (dquote)
6784 dquote = 0;
6785 else
6786 dquote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02006787 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02006788 end--;
6789 }
6790 else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
6791 if (squote)
6792 squote = 0;
6793 else
6794 squote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02006795 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02006796 end--;
6797 }
6798 else if (*line == '\\' && !squote) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006799 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
6800 * C equivalent value. Other combinations left unchanged (eg: \1).
6801 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006802 int skip = 0;
6803 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
6804 *line = line[1];
6805 skip = 1;
6806 }
6807 else if (line[1] == 'r') {
6808 *line = '\r';
6809 skip = 1;
William Lallemandf9873ba2015-05-05 17:37:14 +02006810 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006811 else if (line[1] == 'n') {
6812 *line = '\n';
6813 skip = 1;
6814 }
6815 else if (line[1] == 't') {
6816 *line = '\t';
6817 skip = 1;
6818 }
6819 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01006820 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006821 unsigned char hex1, hex2;
6822 hex1 = toupper(line[2]) - '0';
6823 hex2 = toupper(line[3]) - '0';
6824 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
6825 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
6826 *line = (hex1<<4) + hex2;
6827 skip = 3;
6828 }
6829 else {
6830 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006831 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006832 }
William Lallemandf9873ba2015-05-05 17:37:14 +02006833 } else if (line[1] == '"') {
6834 *line = '"';
6835 skip = 1;
6836 } else if (line[1] == '\'') {
6837 *line = '\'';
6838 skip = 1;
William Lallemandb2f07452015-05-12 14:27:13 +02006839 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
6840 *line = '$';
6841 skip = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006842 }
6843 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01006844 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006845 end -= skip;
6846 }
6847 line++;
6848 }
William Lallemandf9873ba2015-05-05 17:37:14 +02006849 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006850 /* end of string, end of loop */
6851 *line = 0;
6852 break;
6853 }
William Lallemandf9873ba2015-05-05 17:37:14 +02006854 else if (!squote && !dquote && isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006855 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006856 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006857 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006858 line++;
6859 args[++arg] = line;
6860 }
William Lallemandb2f07452015-05-12 14:27:13 +02006861 else if (dquote && *line == '$') {
6862 /* environment variables are evaluated inside double quotes */
6863 char *var_beg;
6864 char *var_end;
6865 char save_char;
6866 char *value;
6867 int val_len;
6868 int newlinesize;
6869 int braces = 0;
6870
6871 var_beg = line + 1;
6872 var_end = var_beg;
6873
6874 if (*var_beg == '{') {
6875 var_beg++;
6876 var_end++;
6877 braces = 1;
6878 }
6879
6880 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
6881 Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
6882 err_code |= ERR_ALERT | ERR_FATAL;
6883 goto next_line; /* skip current line */
6884 }
6885
6886 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
6887 var_end++;
6888
6889 save_char = *var_end;
6890 *var_end = '\0';
6891 value = getenv(var_beg);
6892 *var_end = save_char;
6893 val_len = value ? strlen(value) : 0;
6894
6895 if (braces) {
6896 if (*var_end == '}') {
6897 var_end++;
6898 braces = 0;
6899 } else {
6900 Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
6901 err_code |= ERR_ALERT | ERR_FATAL;
6902 goto next_line; /* skip current line */
6903 }
6904 }
6905
6906 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
6907
6908 /* if not enough space in thisline */
6909 if (newlinesize > linesize) {
6910 char *newline;
6911
6912 newline = realloc(thisline, newlinesize * sizeof(*thisline));
6913 if (newline == NULL) {
6914 Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
6915 err_code |= ERR_ALERT | ERR_FATAL;
6916 goto next_line; /* slip current line */
6917 }
6918 /* recompute pointers if realloc returns a new pointer */
6919 if (newline != thisline) {
6920 int i;
6921 int diff;
6922
6923 for (i = 0; i <= arg; i++) {
6924 diff = args[i] - thisline;
6925 args[i] = newline + diff;
6926 }
6927
6928 diff = var_end - thisline;
6929 var_end = newline + diff;
6930 diff = end - thisline;
6931 end = newline + diff;
6932 diff = line - thisline;
6933 line = newline + diff;
6934 thisline = newline;
6935 }
6936 linesize = newlinesize;
6937 }
6938
6939 /* insert value inside the line */
6940 memmove(line + val_len, var_end, end - var_end + 1);
6941 memcpy(line, value, val_len);
6942 end += val_len - (var_end - line);
6943 line += val_len;
6944 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006945 else {
6946 line++;
6947 }
6948 }
William Lallemandb2f07452015-05-12 14:27:13 +02006949
William Lallemandf9873ba2015-05-05 17:37:14 +02006950 if (dquote) {
6951 Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
6952 err_code |= ERR_ALERT | ERR_FATAL;
6953 }
6954
6955 if (squote) {
6956 Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
6957 err_code |= ERR_ALERT | ERR_FATAL;
6958 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006959
6960 /* empty line */
6961 if (!**args)
6962 continue;
6963
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006964 if (*line) {
6965 /* we had to stop due to too many args.
6966 * Let's terminate the string, print the offending part then cut the
6967 * last arg.
6968 */
6969 while (*line && *line != '#' && *line != '\n' && *line != '\r')
6970 line++;
6971 *line = '\0';
6972
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01006973 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01006974 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006975 err_code |= ERR_ALERT | ERR_FATAL;
6976 args[arg] = line;
6977 }
6978
Willy Tarreau540abe42007-05-02 20:50:16 +02006979 /* zero out remaining args and ensure that at least one entry
6980 * is zeroed out.
6981 */
6982 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006983 args[arg] = line;
6984 }
6985
Willy Tarreau3842f002009-06-14 11:39:52 +02006986 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006987 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006988 char *tmp;
6989
Willy Tarreau3842f002009-06-14 11:39:52 +02006990 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02006991 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006992 for (arg=0; *args[arg+1]; arg++)
6993 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02006994 *tmp = '\0'; // fix the next arg to \0
6995 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006996 }
Willy Tarreau3842f002009-06-14 11:39:52 +02006997 else if (!strcmp(args[0], "default")) {
6998 kwm = KWM_DEF;
6999 for (arg=0; *args[arg+1]; arg++)
7000 args[arg] = args[arg+1]; // shift args after inversion
7001 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007002
William Lallemand0f99e342011-10-12 17:50:54 +02007003 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
7004 strcmp(args[0], "log") != 0) {
7005 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02007006 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007007 }
7008
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007009 /* detect section start */
7010 list_for_each_entry(ics, &sections, list) {
7011 if (strcmp(args[0], ics->section_name) == 0) {
7012 cursection = ics->section_name;
7013 cs = ics;
7014 break;
7015 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007016 }
7017
Willy Tarreaubaaee002006-06-26 02:48:02 +02007018 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007019 if (cs)
7020 err_code |= cs->section_parser(file, linenum, args, kwm);
7021 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007022 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007023 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007024 }
Willy Tarreau058e9072009-07-20 09:30:05 +02007025
7026 if (err_code & ERR_ABORT)
7027 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007028 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01007029 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02007030 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007031 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02007032 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007033}
7034
Willy Tarreau64ab6072014-09-16 12:17:36 +02007035/* This function propagates processes from frontend <from> to backend <to> so
7036 * that it is always guaranteed that a backend pointed to by a frontend is
7037 * bound to all of its processes. After that, if the target is a "listen"
7038 * instance, the function recursively descends the target's own targets along
Willy Tarreau98d04852015-05-26 12:18:29 +02007039 * default_backend and use_backend rules. Since the bits are
Willy Tarreau64ab6072014-09-16 12:17:36 +02007040 * checked first to ensure that <to> is already bound to all processes of
7041 * <from>, there is no risk of looping and we ensure to follow the shortest
7042 * path to the destination.
7043 *
7044 * It is possible to set <to> to NULL for the first call so that the function
7045 * takes care of visiting the initial frontend in <from>.
7046 *
7047 * It is important to note that the function relies on the fact that all names
7048 * have already been resolved.
7049 */
7050void propagate_processes(struct proxy *from, struct proxy *to)
7051{
7052 struct switching_rule *rule;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007053
7054 if (to) {
7055 /* check whether we need to go down */
7056 if (from->bind_proc &&
7057 (from->bind_proc & to->bind_proc) == from->bind_proc)
7058 return;
7059
7060 if (!from->bind_proc && !to->bind_proc)
7061 return;
7062
7063 to->bind_proc = from->bind_proc ?
7064 (to->bind_proc | from->bind_proc) : 0;
7065
7066 /* now propagate down */
7067 from = to;
7068 }
7069
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01007070 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02007071 return;
7072
Willy Tarreauf6b70012014-12-18 14:00:43 +01007073 if (from->state == PR_STSTOPPED)
7074 return;
7075
Willy Tarreau64ab6072014-09-16 12:17:36 +02007076 /* default_backend */
7077 if (from->defbe.be)
7078 propagate_processes(from, from->defbe.be);
7079
7080 /* use_backend */
7081 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02007082 if (rule->dynamic)
7083 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007084 to = rule->be.backend;
7085 propagate_processes(from, to);
7086 }
Willy Tarreau64ab6072014-09-16 12:17:36 +02007087}
7088
Willy Tarreaubb925012009-07-23 13:36:36 +02007089/*
7090 * Returns the error code, 0 if OK, or any combination of :
7091 * - ERR_ABORT: must abort ASAP
7092 * - ERR_FATAL: we can continue parsing but not start the service
7093 * - ERR_WARN: a warning has been emitted
7094 * - ERR_ALERT: an alert has been emitted
7095 * Only the two first ones can stop processing, the two others are just
7096 * indicators.
7097 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007098int check_config_validity()
7099{
7100 int cfgerr = 0;
7101 struct proxy *curproxy = NULL;
7102 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02007103 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007104 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007105 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007106
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007107 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007108 /*
7109 * Now, check for the integrity of all that we have collected.
7110 */
7111
7112 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02007113 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007114
Willy Tarreau193b8c62012-11-22 00:17:38 +01007115 if (!global.tune.max_http_hdr)
7116 global.tune.max_http_hdr = MAX_HTTP_HDR;
7117
7118 if (!global.tune.cookie_len)
7119 global.tune.cookie_len = CAPTURE_LEN;
7120
7121 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
7122
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007123 /* Post initialisation of the users and groups lists. */
7124 err_code = userlist_postinit();
7125 if (err_code != ERR_NONE)
7126 goto out;
7127
Willy Tarreau55bc0f82009-03-15 14:51:53 +01007128 /* first, we will invert the proxy list order */
7129 curproxy = NULL;
7130 while (proxy) {
7131 struct proxy *next;
7132
7133 next = proxy->next;
7134 proxy->next = curproxy;
7135 curproxy = proxy;
7136 if (!next)
7137 break;
7138 proxy = next;
7139 }
7140
Willy Tarreau419ead82014-09-16 13:41:21 +02007141 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007142 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007143 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01007144 struct sticking_rule *mrule;
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007145 struct act_rule *trule;
7146 struct act_rule *hrqrule;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007147 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01007148 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007149
Willy Tarreau050536d2012-10-04 08:47:34 +02007150 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007151 /* proxy ID not set, use automatic numbering with first
7152 * spare entry starting with next_pxid.
7153 */
7154 next_pxid = get_next_id(&used_proxy_id, next_pxid);
7155 curproxy->conf.id.key = curproxy->uuid = next_pxid;
7156 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007157 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007158 next_pxid++;
7159
Willy Tarreau55ea7572007-06-17 19:56:27 +02007160
Willy Tarreaubaaee002006-06-26 02:48:02 +02007161 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02007162 /* ensure we don't keep listeners uselessly bound */
7163 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02007164 free((void *)curproxy->table.peers.name);
7165 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007166 continue;
7167 }
7168
Willy Tarreau102df612014-05-07 23:56:38 +02007169 /* Check multi-process mode compatibility for the current proxy */
7170
7171 if (curproxy->bind_proc) {
7172 /* an explicit bind-process was specified, let's check how many
7173 * processes remain.
7174 */
David Carliere6c39412015-07-02 07:00:17 +00007175 nbproc = my_popcountl(curproxy->bind_proc);
Willy Tarreau102df612014-05-07 23:56:38 +02007176
7177 curproxy->bind_proc &= nbits(global.nbproc);
7178 if (!curproxy->bind_proc && nbproc == 1) {
7179 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);
7180 curproxy->bind_proc = 1;
7181 }
7182 else if (!curproxy->bind_proc && nbproc > 1) {
7183 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);
7184 curproxy->bind_proc = 0;
7185 }
7186 }
7187
Willy Tarreau3d209582014-05-09 17:06:11 +02007188 /* check and reduce the bind-proc of each listener */
7189 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7190 unsigned long mask;
7191
7192 if (!bind_conf->bind_proc)
7193 continue;
7194
7195 mask = nbits(global.nbproc);
7196 if (curproxy->bind_proc)
7197 mask &= curproxy->bind_proc;
7198 /* mask cannot be null here thanks to the previous checks */
7199
David Carliere6c39412015-07-02 07:00:17 +00007200 nbproc = my_popcountl(bind_conf->bind_proc);
Willy Tarreau3d209582014-05-09 17:06:11 +02007201 bind_conf->bind_proc &= mask;
7202
7203 if (!bind_conf->bind_proc && nbproc == 1) {
7204 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",
7205 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7206 bind_conf->bind_proc = mask & ~(mask - 1);
7207 }
7208 else if (!bind_conf->bind_proc && nbproc > 1) {
7209 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",
7210 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7211 bind_conf->bind_proc = 0;
7212 }
7213 }
7214
Willy Tarreauff01a212009-03-15 13:46:16 +01007215 switch (curproxy->mode) {
7216 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007217 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007218 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007219 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
7220 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007221 cfgerr++;
7222 }
7223
7224 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007225 Warning("config : servers will be ignored for %s '%s'.\n",
7226 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007227 break;
7228
7229 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007230 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007231 break;
7232
7233 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01007234 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01007235 break;
7236 }
7237
Willy Tarreauf3934b82015-08-11 11:36:45 +02007238 if ((curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->conf.listeners)) {
7239 Warning("config : %s '%s' has no 'bind' directive. Please declare it as a backend if this was intended.\n",
7240 proxy_type_str(curproxy), curproxy->id);
7241 err_code |= ERR_WARN;
7242 }
7243
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007244 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007245 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007246 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007247 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
7248 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007249 cfgerr++;
7250 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007251#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007252 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007253 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
7254 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007255 cfgerr++;
7256 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007257#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02007258 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007259 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
7260 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007261 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007262 }
7263 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02007264 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007265 /* If no LB algo is set in a backend, and we're not in
7266 * transparent mode, dispatch mode nor proxy mode, we
7267 * want to use balance roundrobin by default.
7268 */
7269 curproxy->lbprm.algo &= ~BE_LB_ALGO;
7270 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007271 }
7272 }
Willy Tarreau193cf932007-09-17 10:17:23 +02007273
Willy Tarreau1620ec32011-08-06 17:05:02 +02007274 if (curproxy->options & PR_O_DISPATCH)
7275 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
7276 else if (curproxy->options & PR_O_HTTP_PROXY)
7277 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
7278 else if (curproxy->options & PR_O_TRANSP)
7279 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01007280
Willy Tarreau1620ec32011-08-06 17:05:02 +02007281 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
7282 if (curproxy->options & PR_O_DISABLE404) {
7283 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7284 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
7285 err_code |= ERR_WARN;
7286 curproxy->options &= ~PR_O_DISABLE404;
7287 }
7288 if (curproxy->options2 & PR_O2_CHK_SNDST) {
7289 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7290 "send-state", proxy_type_str(curproxy), curproxy->id);
7291 err_code |= ERR_WARN;
7292 curproxy->options &= ~PR_O2_CHK_SNDST;
7293 }
Willy Tarreauef781042010-01-27 11:53:01 +01007294 }
7295
Simon Horman98637e52014-06-20 12:30:16 +09007296 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
7297 if (!global.external_check) {
7298 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
7299 curproxy->id, "option external-check");
7300 cfgerr++;
7301 }
7302 if (!curproxy->check_command) {
7303 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
7304 curproxy->id, "option external-check");
7305 cfgerr++;
7306 }
7307 }
7308
Simon Horman64e34162015-02-06 11:11:57 +09007309 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007310 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
7311 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Pieter Baauw8669e972015-08-17 00:45:05 +02007312 "'email-alert from', 'email-alert level' 'email-alert mailers', "
7313 "'email-alert myhostname', or 'email-alert to' "
7314 "requires each of 'email-alert from', 'email-alert mailers' and 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007315 "to be present).\n",
7316 proxy_type_str(curproxy), curproxy->id);
7317 err_code |= ERR_WARN;
7318 free_email_alert(curproxy);
7319 }
7320 if (!curproxy->email_alert.myhostname)
7321 curproxy->email_alert.myhostname = hostname;
Simon Horman9dc49962015-01-30 11:22:59 +09007322 }
7323
Simon Horman98637e52014-06-20 12:30:16 +09007324 if (curproxy->check_command) {
7325 int clear = 0;
7326 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7327 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7328 "external-check command", proxy_type_str(curproxy), curproxy->id);
7329 err_code |= ERR_WARN;
7330 clear = 1;
7331 }
7332 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
7333 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-command path' is not set.\n",
7334 curproxy->id, "external-check command");
7335 cfgerr++;
7336 }
7337 if (clear) {
7338 free(curproxy->check_command);
7339 curproxy->check_command = NULL;
7340 }
7341 }
7342
7343 if (curproxy->check_path) {
7344 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7345 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7346 "external-check path", proxy_type_str(curproxy), curproxy->id);
7347 err_code |= ERR_WARN;
7348 free(curproxy->check_path);
7349 curproxy->check_path = NULL;
7350 }
7351 }
7352
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007353 /* if a default backend was specified, let's find it */
7354 if (curproxy->defbe.name) {
7355 struct proxy *target;
7356
Willy Tarreauafb39922015-05-26 12:04:09 +02007357 target = proxy_be_by_name(curproxy->defbe.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007358 if (!target) {
7359 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
7360 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007361 cfgerr++;
7362 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007363 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
7364 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02007365 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007366 } else if (target->mode != curproxy->mode &&
7367 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7368
7369 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) as its default backend (see 'mode').\n",
7370 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7371 curproxy->conf.file, curproxy->conf.line,
7372 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7373 target->conf.file, target->conf.line);
7374 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007375 } else {
7376 free(curproxy->defbe.name);
7377 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01007378
7379 /* Emit a warning if this proxy also has some servers */
7380 if (curproxy->srv) {
7381 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
7382 curproxy->id);
7383 err_code |= ERR_WARN;
7384 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007385 }
7386 }
7387
Willy Tarreau55ea7572007-06-17 19:56:27 +02007388 /* find the target proxy for 'use_backend' rules */
7389 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007390 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007391 struct logformat_node *node;
7392 char *pxname;
7393
7394 /* Try to parse the string as a log format expression. If the result
7395 * of the parsing is only one entry containing a simple string, then
7396 * it's a standard string corresponding to a static rule, thus the
7397 * parsing is cancelled and be.name is restored to be resolved.
7398 */
7399 pxname = rule->be.name;
7400 LIST_INIT(&rule->be.expr);
7401 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
7402 curproxy->conf.args.file, curproxy->conf.args.line);
7403 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
7404
7405 if (!LIST_ISEMPTY(&rule->be.expr)) {
7406 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
7407 rule->dynamic = 1;
7408 free(pxname);
7409 continue;
7410 }
7411 /* simple string: free the expression and fall back to static rule */
7412 free(node->arg);
7413 free(node);
7414 }
7415
7416 rule->dynamic = 0;
7417 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007418
Willy Tarreauafb39922015-05-26 12:04:09 +02007419 target = proxy_be_by_name(rule->be.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007420 if (!target) {
7421 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
7422 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007423 cfgerr++;
7424 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007425 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
7426 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007427 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007428 } else if (target->mode != curproxy->mode &&
7429 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7430
7431 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) in a 'use_backend' rule (see 'mode').\n",
7432 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7433 curproxy->conf.file, curproxy->conf.line,
7434 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7435 target->conf.file, target->conf.line);
7436 cfgerr++;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007437 } else {
7438 free((void *)rule->be.name);
7439 rule->be.backend = target;
7440 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007441 }
7442
Willy Tarreau64ab6072014-09-16 12:17:36 +02007443 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007444 list_for_each_entry(srule, &curproxy->server_rules, list) {
7445 struct server *target = findserver(curproxy, srule->srv.name);
7446
7447 if (!target) {
7448 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7449 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7450 cfgerr++;
7451 continue;
7452 }
7453 free((void *)srule->srv.name);
7454 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007455 }
7456
Emeric Brunb982a3d2010-01-04 15:45:53 +01007457 /* find the target table for 'stick' rules */
7458 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7459 struct proxy *target;
7460
Emeric Brun1d33b292010-01-04 15:47:17 +01007461 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7462 if (mrule->flags & STK_IS_STORE)
7463 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7464
Emeric Brunb982a3d2010-01-04 15:45:53 +01007465 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007466 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007467 else
7468 target = curproxy;
7469
7470 if (!target) {
7471 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7472 curproxy->id, mrule->table.name);
7473 cfgerr++;
7474 }
7475 else if (target->table.size == 0) {
7476 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7477 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7478 cfgerr++;
7479 }
Willy Tarreau12785782012-04-27 21:37:17 +02007480 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7481 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007482 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7483 cfgerr++;
7484 }
7485 else {
7486 free((void *)mrule->table.name);
7487 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007488 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007489 }
7490 }
7491
7492 /* find the target table for 'store response' rules */
7493 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7494 struct proxy *target;
7495
Emeric Brun1d33b292010-01-04 15:47:17 +01007496 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7497
Emeric Brunb982a3d2010-01-04 15:45:53 +01007498 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007499 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007500 else
7501 target = curproxy;
7502
7503 if (!target) {
7504 Alert("Proxy '%s': unable to find store table '%s'.\n",
7505 curproxy->id, mrule->table.name);
7506 cfgerr++;
7507 }
7508 else if (target->table.size == 0) {
7509 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7510 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7511 cfgerr++;
7512 }
Willy Tarreau12785782012-04-27 21:37:17 +02007513 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7514 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007515 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7516 cfgerr++;
7517 }
7518 else {
7519 free((void *)mrule->table.name);
7520 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007521 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007522 }
7523 }
7524
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007525 /* find the target table for 'tcp-request' layer 4 rules */
7526 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
7527 struct proxy *target;
7528
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007529 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007530 continue;
7531
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007532 if (trule->arg.trk_ctr.table.n)
7533 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007534 else
7535 target = curproxy;
7536
7537 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007538 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007539 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007540 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007541 cfgerr++;
7542 }
7543 else if (target->table.size == 0) {
7544 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007545 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007546 cfgerr++;
7547 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007548 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007549 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007550 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007551 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007552 cfgerr++;
7553 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007554 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007555 free(trule->arg.trk_ctr.table.n);
7556 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007557 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007558 * to pass a list of counters to track and allocate them right here using
7559 * stktable_alloc_data_type().
7560 */
7561 }
7562 }
7563
Willy Tarreaud1f96522010-08-03 19:34:32 +02007564 /* find the target table for 'tcp-request' layer 6 rules */
7565 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7566 struct proxy *target;
7567
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007568 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02007569 continue;
7570
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007571 if (trule->arg.trk_ctr.table.n)
7572 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007573 else
7574 target = curproxy;
7575
7576 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007577 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007578 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007579 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02007580 cfgerr++;
7581 }
7582 else if (target->table.size == 0) {
7583 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007584 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007585 cfgerr++;
7586 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007587 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007588 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007589 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007590 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007591 cfgerr++;
7592 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02007593 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007594 free(trule->arg.trk_ctr.table.n);
7595 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007596 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02007597 * to pass a list of counters to track and allocate them right here using
7598 * stktable_alloc_data_type().
7599 */
7600 }
7601 }
7602
Willy Tarreau09448f72014-06-25 18:12:15 +02007603 /* find the target table for 'http-request' layer 7 rules */
7604 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7605 struct proxy *target;
7606
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007607 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau09448f72014-06-25 18:12:15 +02007608 continue;
7609
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007610 if (hrqrule->arg.trk_ctr.table.n)
7611 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
Willy Tarreau09448f72014-06-25 18:12:15 +02007612 else
7613 target = curproxy;
7614
7615 if (!target) {
7616 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007617 curproxy->id, hrqrule->arg.trk_ctr.table.n,
Willy Tarreau09448f72014-06-25 18:12:15 +02007618 http_req_trk_idx(hrqrule->action));
7619 cfgerr++;
7620 }
7621 else if (target->table.size == 0) {
7622 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007623 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau09448f72014-06-25 18:12:15 +02007624 cfgerr++;
7625 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007626 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau09448f72014-06-25 18:12:15 +02007627 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007628 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau09448f72014-06-25 18:12:15 +02007629 http_req_trk_idx(hrqrule->action));
7630 cfgerr++;
7631 }
7632 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007633 free(hrqrule->arg.trk_ctr.table.n);
7634 hrqrule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau09448f72014-06-25 18:12:15 +02007635 /* Note: if we decide to enhance the track-sc syntax, we may be able
7636 * to pass a list of counters to track and allocate them right here using
7637 * stktable_alloc_data_type().
7638 */
7639 }
7640 }
7641
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02007642 /* move any "block" rules at the beginning of the http-request rules */
7643 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
7644 /* insert block_rules into http_req_rules at the beginning */
7645 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
7646 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
7647 curproxy->block_rules.n->p = &curproxy->http_req_rules;
7648 curproxy->http_req_rules.n = curproxy->block_rules.n;
7649 LIST_INIT(&curproxy->block_rules);
7650 }
7651
Emeric Brun32da3c42010-09-23 18:39:19 +02007652 if (curproxy->table.peers.name) {
7653 struct peers *curpeers = peers;
7654
7655 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
7656 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
7657 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01007658 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02007659 break;
7660 }
7661 }
7662
7663 if (!curpeers) {
7664 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
7665 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007666 free((void *)curproxy->table.peers.name);
7667 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007668 cfgerr++;
7669 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02007670 else if (curpeers->state == PR_STSTOPPED) {
7671 /* silently disable this peers section */
7672 curproxy->table.peers.p = NULL;
7673 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007674 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02007675 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
7676 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007677 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007678 cfgerr++;
7679 }
7680 }
7681
Simon Horman9dc49962015-01-30 11:22:59 +09007682
7683 if (curproxy->email_alert.mailers.name) {
7684 struct mailers *curmailers = mailers;
7685
7686 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
7687 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
7688 free(curproxy->email_alert.mailers.name);
7689 curproxy->email_alert.mailers.m = curmailers;
7690 curmailers->users++;
7691 break;
7692 }
7693 }
7694
7695 if (!curmailers) {
7696 Alert("Proxy '%s': unable to find mailers '%s'.\n",
7697 curproxy->id, curproxy->email_alert.mailers.name);
7698 free_email_alert(curproxy);
7699 cfgerr++;
7700 }
7701 }
7702
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007703 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01007704 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007705 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
7706 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
7707 "proxy", curproxy->id);
7708 cfgerr++;
7709 goto out_uri_auth_compat;
7710 }
7711
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007712 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007713 const char *uri_auth_compat_req[10];
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007714 struct act_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01007715 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007716
Willy Tarreau95fa4692010-02-01 13:05:50 +01007717 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
7718 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007719
7720 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007721 uri_auth_compat_req[i++] = "realm";
7722 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
7723 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007724
Willy Tarreau95fa4692010-02-01 13:05:50 +01007725 uri_auth_compat_req[i++] = "unless";
7726 uri_auth_compat_req[i++] = "{";
7727 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
7728 uri_auth_compat_req[i++] = "}";
7729 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007730
Willy Tarreauff011f22011-01-06 17:51:27 +01007731 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
7732 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007733 cfgerr++;
7734 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007735 }
7736
Willy Tarreauff011f22011-01-06 17:51:27 +01007737 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01007738
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007739 if (curproxy->uri_auth->auth_realm) {
7740 free(curproxy->uri_auth->auth_realm);
7741 curproxy->uri_auth->auth_realm = NULL;
7742 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007743
7744 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007745 }
7746out_uri_auth_compat:
7747
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007748 /* compile the log format */
7749 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02007750 if (curproxy->conf.logformat_string != default_http_log_format &&
7751 curproxy->conf.logformat_string != default_tcp_log_format &&
7752 curproxy->conf.logformat_string != clf_http_log_format)
7753 free(curproxy->conf.logformat_string);
7754 curproxy->conf.logformat_string = NULL;
7755 free(curproxy->conf.lfs_file);
7756 curproxy->conf.lfs_file = NULL;
7757 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007758 }
7759
Willy Tarreau62a61232013-04-12 18:13:46 +02007760 if (curproxy->conf.logformat_string) {
7761 curproxy->conf.args.ctx = ARGC_LOG;
7762 curproxy->conf.args.file = curproxy->conf.lfs_file;
7763 curproxy->conf.args.line = curproxy->conf.lfs_line;
7764 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007765 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007766 curproxy->conf.args.file = NULL;
7767 curproxy->conf.args.line = 0;
7768 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007769
Willy Tarreau62a61232013-04-12 18:13:46 +02007770 if (curproxy->conf.uniqueid_format_string) {
7771 curproxy->conf.args.ctx = ARGC_UIF;
7772 curproxy->conf.args.file = curproxy->conf.uif_file;
7773 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01007774 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Godbachd9722032014-12-18 15:44:58 +08007775 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007776 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007777 curproxy->conf.args.file = NULL;
7778 curproxy->conf.args.line = 0;
7779 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007780
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007781 /* only now we can check if some args remain unresolved.
7782 * This must be done after the users and groups resolution.
7783 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007784 cfgerr += smp_resolve_args(curproxy);
7785 if (!cfgerr)
7786 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01007787
Willy Tarreau2738a142006-07-08 17:28:09 +02007788 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007789 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02007790 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02007791 (!curproxy->timeout.connect ||
7792 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007793 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02007794 " | While not properly invalid, you will certainly encounter various problems\n"
7795 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01007796 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007797 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007798 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02007799 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02007800
Willy Tarreau1fa31262007-12-03 00:36:16 +01007801 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
7802 * We must still support older configurations, so let's find out whether those
7803 * parameters have been set or must be copied from contimeouts.
7804 */
7805 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007806 if (!curproxy->timeout.tarpit ||
7807 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007808 /* tarpit timeout not set. We search in the following order:
7809 * default.tarpit, curr.connect, default.connect.
7810 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007811 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007812 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007813 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007814 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007815 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007816 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007817 }
7818 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007819 (!curproxy->timeout.queue ||
7820 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007821 /* queue timeout not set. We search in the following order:
7822 * default.queue, curr.connect, default.connect.
7823 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007824 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007825 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007826 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007827 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007828 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007829 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007830 }
7831 }
7832
Willy Tarreau1620ec32011-08-06 17:05:02 +02007833 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01007834 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
7835 curproxy->check_req = (char *)malloc(curproxy->check_len);
7836 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02007837 }
7838
Willy Tarreau215663d2014-06-13 18:30:23 +02007839 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
7840 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
7841 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
7842 proxy_type_str(curproxy), curproxy->id);
7843 err_code |= ERR_WARN;
7844 }
7845
Willy Tarreau193b8c62012-11-22 00:17:38 +01007846 /* ensure that cookie capture length is not too large */
7847 if (curproxy->capture_len >= global.tune.cookie_len) {
7848 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
7849 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
7850 err_code |= ERR_WARN;
7851 curproxy->capture_len = global.tune.cookie_len - 1;
7852 }
7853
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007854 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01007855 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02007856 curproxy->req_cap_pool = create_pool("ptrcap",
7857 curproxy->nb_req_cap * sizeof(char *),
7858 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01007859 }
7860
7861 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02007862 curproxy->rsp_cap_pool = create_pool("ptrcap",
7863 curproxy->nb_rsp_cap * sizeof(char *),
7864 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01007865 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007866
Willy Tarreaubaaee002006-06-26 02:48:02 +02007867 /* first, we will invert the servers list order */
7868 newsrv = NULL;
7869 while (curproxy->srv) {
7870 struct server *next;
7871
7872 next = curproxy->srv->next;
7873 curproxy->srv->next = newsrv;
7874 newsrv = curproxy->srv;
7875 if (!next)
7876 break;
7877 curproxy->srv = next;
7878 }
7879
Willy Tarreau17edc812014-01-03 12:14:34 +01007880 /* Check that no server name conflicts. This causes trouble in the stats.
7881 * We only emit a warning for the first conflict affecting each server,
7882 * in order to avoid combinatory explosion if all servers have the same
7883 * name. We do that only for servers which do not have an explicit ID,
7884 * because these IDs were made also for distinguishing them and we don't
7885 * want to annoy people who correctly manage them.
7886 */
7887 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
7888 struct server *other_srv;
7889
7890 if (newsrv->puid)
7891 continue;
7892
7893 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
7894 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
7895 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
7896 newsrv->conf.file, newsrv->conf.line,
7897 proxy_type_str(curproxy), curproxy->id,
7898 newsrv->id, other_srv->conf.line);
7899 break;
7900 }
7901 }
7902 }
7903
Willy Tarreaudd701652010-05-25 23:03:02 +02007904 /* assign automatic UIDs to servers which don't have one yet */
7905 next_id = 1;
7906 newsrv = curproxy->srv;
7907 while (newsrv != NULL) {
7908 if (!newsrv->puid) {
7909 /* server ID not set, use automatic numbering with first
7910 * spare entry starting with next_svid.
7911 */
7912 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
7913 newsrv->conf.id.key = newsrv->puid = next_id;
7914 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
7915 }
7916 next_id++;
7917 newsrv = newsrv->next;
7918 }
7919
Willy Tarreau20697042007-11-15 23:26:18 +01007920 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01007921 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007922
Willy Tarreau62c3be22012-01-20 13:12:32 +01007923 /*
7924 * If this server supports a maxconn parameter, it needs a dedicated
7925 * tasks to fill the emptied slots when a connection leaves.
7926 * Also, resolve deferred tracking dependency if needed.
7927 */
7928 newsrv = curproxy->srv;
7929 while (newsrv != NULL) {
7930 if (newsrv->minconn > newsrv->maxconn) {
7931 /* Only 'minconn' was specified, or it was higher than or equal
7932 * to 'maxconn'. Let's turn this into maxconn and clean it, as
7933 * this will avoid further useless expensive computations.
7934 */
7935 newsrv->maxconn = newsrv->minconn;
7936 } else if (newsrv->maxconn && !newsrv->minconn) {
7937 /* minconn was not specified, so we set it to maxconn */
7938 newsrv->minconn = newsrv->maxconn;
7939 }
7940
Emeric Brun01f8e2f2012-05-18 16:02:00 +02007941#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02007942 if (newsrv->use_ssl || newsrv->check.use_ssl)
7943 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02007944#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02007945
Willy Tarreau2f075e92013-12-03 11:11:34 +01007946 /* set the check type on the server */
7947 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
7948
Willy Tarreau62c3be22012-01-20 13:12:32 +01007949 if (newsrv->trackit) {
7950 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02007951 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007952 char *pname, *sname;
7953
7954 pname = newsrv->trackit;
7955 sname = strrchr(pname, '/');
7956
7957 if (sname)
7958 *sname++ = '\0';
7959 else {
7960 sname = pname;
7961 pname = NULL;
7962 }
7963
7964 if (pname) {
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007965 px = proxy_be_by_name(pname);
Willy Tarreau62c3be22012-01-20 13:12:32 +01007966 if (!px) {
7967 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
7968 proxy_type_str(curproxy), curproxy->id,
7969 newsrv->id, pname);
7970 cfgerr++;
7971 goto next_srv;
7972 }
7973 } else
7974 px = curproxy;
7975
7976 srv = findserver(px, sname);
7977 if (!srv) {
7978 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
7979 proxy_type_str(curproxy), curproxy->id,
7980 newsrv->id, sname);
7981 cfgerr++;
7982 goto next_srv;
7983 }
7984
Willy Tarreau32091232014-05-16 13:52:00 +02007985 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
7986 !(srv->agent.state & CHK_ST_CONFIGURED) &&
7987 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01007988 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02007989 "tracking as it does not have any check nor agent enabled.\n",
7990 proxy_type_str(curproxy), curproxy->id,
7991 newsrv->id, px->id, srv->id);
7992 cfgerr++;
7993 goto next_srv;
7994 }
7995
7996 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
7997
7998 if (loop) {
7999 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
8000 "belongs to a tracking chain looping back to %s/%s.\n",
8001 proxy_type_str(curproxy), curproxy->id,
8002 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008003 cfgerr++;
8004 goto next_srv;
8005 }
8006
8007 if (curproxy != px &&
8008 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
8009 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
8010 "tracking: disable-on-404 option inconsistency.\n",
8011 proxy_type_str(curproxy), curproxy->id,
8012 newsrv->id, px->id, srv->id);
8013 cfgerr++;
8014 goto next_srv;
8015 }
8016
8017 /* if the other server is forced disabled, we have to do the same here */
Willy Tarreau20125212014-05-13 19:44:56 +02008018 if (srv->admin & SRV_ADMF_MAINT) {
Willy Tarreaua0066dd2014-05-16 11:25:16 +02008019 newsrv->admin |= SRV_ADMF_IMAINT;
Willy Tarreau892337c2014-05-13 23:41:20 +02008020 newsrv->state = SRV_ST_STOPPED;
Simon Horman125d0992013-02-24 17:23:38 +09008021 newsrv->check.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008022 }
8023
8024 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01008025 newsrv->tracknext = srv->trackers;
8026 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008027
8028 free(newsrv->trackit);
8029 newsrv->trackit = NULL;
8030 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008031
8032 /*
8033 * resolve server's resolvers name and update the resolvers pointer
8034 * accordingly
8035 */
8036 if (newsrv->resolvers_id) {
8037 struct dns_resolvers *curr_resolvers;
8038 int found;
8039
8040 found = 0;
8041 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
8042 if (!strcmp(curr_resolvers->id, newsrv->resolvers_id)) {
8043 found = 1;
8044 break;
8045 }
8046 }
8047
8048 if (!found) {
8049 Alert("config : %s '%s', server '%s': unable to find required resolvers '%s'\n",
8050 proxy_type_str(curproxy), curproxy->id,
8051 newsrv->id, newsrv->resolvers_id);
8052 cfgerr++;
8053 } else {
8054 free(newsrv->resolvers_id);
8055 newsrv->resolvers_id = NULL;
8056 if (newsrv->resolution)
8057 newsrv->resolution->resolvers = curr_resolvers;
8058 }
8059 }
8060 else {
8061 /* if no resolvers section associated to this server
8062 * we can clean up the associated resolution structure
8063 */
8064 if (newsrv->resolution) {
8065 free(newsrv->resolution->hostname_dn);
8066 newsrv->resolution->hostname_dn = NULL;
8067 free(newsrv->resolution);
8068 newsrv->resolution = NULL;
8069 }
8070 }
8071
Willy Tarreau62c3be22012-01-20 13:12:32 +01008072 next_srv:
8073 newsrv = newsrv->next;
8074 }
8075
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008076 /* We have to initialize the server lookup mechanism depending
8077 * on what LB algorithm was choosen.
8078 */
8079
8080 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
8081 switch (curproxy->lbprm.algo & BE_LB_KIND) {
8082 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02008083 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
8084 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8085 init_server_map(curproxy);
8086 } else {
8087 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
8088 fwrr_init_server_groups(curproxy);
8089 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008090 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008091
Willy Tarreau3ebb1162012-02-13 16:57:44 +01008092 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01008093 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
8094 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
8095 fwlc_init_server_tree(curproxy);
8096 } else {
8097 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
8098 fas_init_server_tree(curproxy);
8099 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008100 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008101
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008102 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008103 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
8104 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
8105 chash_init_server_tree(curproxy);
8106 } else {
8107 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8108 init_server_map(curproxy);
8109 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008110 break;
8111 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02008112
8113 if (curproxy->options & PR_O_LOGASAP)
8114 curproxy->to_log &= ~LW_BYTES;
8115
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008116 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01008117 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008118 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
8119 proxy_type_str(curproxy), curproxy->id);
8120 err_code |= ERR_WARN;
8121 }
8122
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008123 if (curproxy->mode != PR_MODE_HTTP) {
8124 int optnum;
8125
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008126 if (curproxy->uri_auth) {
8127 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
8128 proxy_type_str(curproxy), curproxy->id);
8129 err_code |= ERR_WARN;
8130 curproxy->uri_auth = NULL;
8131 }
8132
Willy Tarreau87cf5142011-08-19 22:57:24 +02008133 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008134 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8135 "forwardfor", proxy_type_str(curproxy), curproxy->id);
8136 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02008137 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008138 }
8139
8140 if (curproxy->options & PR_O_ORGTO) {
8141 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8142 "originalto", proxy_type_str(curproxy), curproxy->id);
8143 err_code |= ERR_WARN;
8144 curproxy->options &= ~PR_O_ORGTO;
8145 }
8146
8147 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
8148 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
8149 (curproxy->cap & cfg_opts[optnum].cap) &&
8150 (curproxy->options & cfg_opts[optnum].val)) {
8151 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8152 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
8153 err_code |= ERR_WARN;
8154 curproxy->options &= ~cfg_opts[optnum].val;
8155 }
8156 }
8157
8158 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
8159 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
8160 (curproxy->cap & cfg_opts2[optnum].cap) &&
8161 (curproxy->options2 & cfg_opts2[optnum].val)) {
8162 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8163 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
8164 err_code |= ERR_WARN;
8165 curproxy->options2 &= ~cfg_opts2[optnum].val;
8166 }
8167 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008168
Willy Tarreau29fbe512015-08-20 19:35:14 +02008169#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008170 if (curproxy->conn_src.bind_hdr_occ) {
8171 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008172 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01008173 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008174 err_code |= ERR_WARN;
8175 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008176#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008177 }
8178
Willy Tarreaubaaee002006-06-26 02:48:02 +02008179 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01008180 * ensure that we're not cross-dressing a TCP server into HTTP.
8181 */
8182 newsrv = curproxy->srv;
8183 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01008184 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008185 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
8186 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008187 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01008188 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008189
Willy Tarreau0cec3312011-10-31 13:49:26 +01008190 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
8191 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
8192 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8193 err_code |= ERR_WARN;
8194 }
8195
Willy Tarreauc93cd162014-05-13 15:54:22 +02008196 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02008197 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
8198 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8199 err_code |= ERR_WARN;
8200 }
8201
Willy Tarreau29fbe512015-08-20 19:35:14 +02008202#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008203 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
8204 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008205 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 +01008206 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008207 err_code |= ERR_WARN;
8208 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008209#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01008210 newsrv = newsrv->next;
8211 }
8212
Willy Tarreaue42bd962014-09-16 16:21:19 +02008213 /* check if we have a frontend with "tcp-request content" looking at L7
8214 * with no inspect-delay
8215 */
8216 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
8217 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008218 if (trule->action == ACT_TCP_CAPTURE &&
Thierry FOURNIERd0d65ae2015-08-04 08:21:12 +02008219 !(trule->arg.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008220 break;
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008221 if ((trule->action >= ACT_ACTION_TRK_SC0 && trule->action <= ACT_ACTION_TRK_SCMAX) &&
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008222 !(trule->arg.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008223 break;
8224 }
8225
8226 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
8227 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
8228 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
8229 " This means that these rules will randomly find their contents. This can be fixed by"
8230 " setting the tcp-request inspect-delay.\n",
8231 proxy_type_str(curproxy), curproxy->id);
8232 err_code |= ERR_WARN;
8233 }
8234 }
8235
Willy Tarreauc1a21672009-08-16 22:37:44 +02008236 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02008237 if (!curproxy->accept)
8238 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02008239
Willy Tarreauc1a21672009-08-16 22:37:44 +02008240 if (curproxy->tcp_req.inspect_delay ||
8241 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02008242 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008243
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008244 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008245 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008246 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008247 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008248
8249 /* both TCP and HTTP must check switching rules */
8250 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
8251 }
8252
8253 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02008254 if (curproxy->tcp_req.inspect_delay ||
8255 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
8256 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
8257
Emeric Brun97679e72010-09-23 17:56:44 +02008258 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
8259 curproxy->be_rsp_ana |= AN_RES_INSPECT;
8260
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008261 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008262 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008263 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008264 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008265
8266 /* If the backend does requires RDP cookie persistence, we have to
8267 * enable the corresponding analyser.
8268 */
8269 if (curproxy->options2 & PR_O2_RDPC_PRST)
8270 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
8271 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008272 }
8273
8274 /***********************************************************/
8275 /* At this point, target names have already been resolved. */
8276 /***********************************************************/
8277
8278 /* Check multi-process mode compatibility */
8279
8280 if (global.nbproc > 1 && global.stats_fe) {
8281 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8282 unsigned long mask;
8283
8284 mask = nbits(global.nbproc);
8285 if (global.stats_fe->bind_proc)
8286 mask &= global.stats_fe->bind_proc;
8287
8288 if (bind_conf->bind_proc)
8289 mask &= bind_conf->bind_proc;
8290
8291 /* stop here if more than one process is used */
David Carliere6c39412015-07-02 07:00:17 +00008292 if (my_popcountl(mask) > 1)
Willy Tarreau419ead82014-09-16 13:41:21 +02008293 break;
8294 }
8295 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
8296 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");
8297 }
8298 }
8299
8300 /* Make each frontend inherit bind-process from its listeners when not specified. */
8301 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8302 if (curproxy->bind_proc)
8303 continue;
8304
8305 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8306 unsigned long mask;
8307
Willy Tarreaue428b082015-05-04 21:57:58 +02008308 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008309 curproxy->bind_proc |= mask;
8310 }
8311
8312 if (!curproxy->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008313 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008314 }
8315
8316 if (global.stats_fe) {
8317 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8318 unsigned long mask;
8319
Willy Tarreaue428b082015-05-04 21:57:58 +02008320 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008321 global.stats_fe->bind_proc |= mask;
8322 }
8323 if (!global.stats_fe->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008324 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008325 }
8326
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02008327 /* propagate bindings from frontends to backends. Don't do it if there
8328 * are any fatal errors as we must not call it with unresolved proxies.
8329 */
8330 if (!cfgerr) {
8331 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8332 if (curproxy->cap & PR_CAP_FE)
8333 propagate_processes(curproxy, NULL);
8334 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008335 }
8336
8337 /* Bind each unbound backend to all processes when not specified. */
8338 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8339 if (curproxy->bind_proc)
8340 continue;
Willy Tarreaue428b082015-05-04 21:57:58 +02008341 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008342 }
8343
8344 /*******************************************************/
8345 /* At this step, all proxies have a non-null bind_proc */
8346 /*******************************************************/
8347
8348 /* perform the final checks before creating tasks */
8349
8350 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8351 struct listener *listener;
8352 unsigned int next_id;
8353 int nbproc;
8354
David Carliere6c39412015-07-02 07:00:17 +00008355 nbproc = my_popcountl(curproxy->bind_proc & nbits(global.nbproc));
Willy Tarreauc1a21672009-08-16 22:37:44 +02008356
Emeric Brunc52962f2012-11-15 18:28:02 +01008357#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008358 /* Configure SSL for each bind line.
8359 * Note: if configuration fails at some point, the ->ctx member
8360 * remains NULL so that listeners can later detach.
8361 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008362 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008363 int alloc_ctx;
8364
Emeric Brunc52962f2012-11-15 18:28:02 +01008365 if (!bind_conf->is_ssl) {
8366 if (bind_conf->default_ctx) {
8367 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
8368 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
8369 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008370 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01008371 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008372 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02008373 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008374 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008375 cfgerr++;
8376 continue;
8377 }
8378
Emeric Brun8dc60392014-05-09 13:52:00 +02008379 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008380 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02008381 if (alloc_ctx == SHCTX_E_INIT_LOCK)
8382 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");
8383 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008384 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02008385 cfgerr++;
8386 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008387 }
8388
Emeric Brunfc0421f2012-09-07 17:30:07 +02008389 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008390 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008391
8392 /* initialize CA variables if the certificates generation is enabled */
8393 cfgerr += ssl_sock_load_ca(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008394 }
Emeric Brunc52962f2012-11-15 18:28:02 +01008395#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008396
Willy Tarreaue6b98942007-10-29 01:09:36 +01008397 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008398 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008399 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008400 if (!listener->luid) {
8401 /* listener ID not set, use automatic numbering with first
8402 * spare entry starting with next_luid.
8403 */
8404 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
8405 listener->conf.id.key = listener->luid = next_id;
8406 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008407 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01008408 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008409
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008410 /* enable separate counters */
8411 if (curproxy->options2 & PR_O2_SOCKSTAT) {
8412 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01008413 if (!listener->name)
8414 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008415 }
Willy Tarreau81796be2012-09-22 19:11:47 +02008416
Willy Tarreaue6b98942007-10-29 01:09:36 +01008417 if (curproxy->options & PR_O_TCP_NOLING)
8418 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02008419 if (!listener->maxconn)
8420 listener->maxconn = curproxy->maxconn;
8421 if (!listener->backlog)
8422 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01008423 if (!listener->maxaccept)
8424 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
8425
8426 /* we want to have an optimal behaviour on single process mode to
8427 * maximize the work at once, but in multi-process we want to keep
8428 * some fairness between processes, so we target half of the max
8429 * number of events to be balanced over all the processes the proxy
8430 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
8431 * used to disable the limit.
8432 */
8433 if (listener->maxaccept > 0) {
8434 if (nbproc > 1)
8435 listener->maxaccept = (listener->maxaccept + 1) / 2;
8436 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
8437 }
8438
Willy Tarreau9903f0e2015-04-04 18:50:31 +02008439 listener->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02008440 listener->handler = process_stream;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008441 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01008442 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01008443
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008444 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
8445 listener->options |= LI_O_TCP_RULES;
8446
Willy Tarreaude3041d2010-05-31 10:56:17 +02008447 if (curproxy->mon_mask.s_addr)
8448 listener->options |= LI_O_CHK_MONNET;
8449
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008450 /* smart accept mode is automatic in HTTP mode */
8451 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008452 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008453 !(curproxy->no_options2 & PR_O2_SMARTACC)))
8454 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01008455 }
8456
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008457 /* Release unused SSL configs */
8458 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8459 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008460 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008461#ifdef USE_OPENSSL
Christopher Faulet31af49d2015-06-09 17:29:50 +02008462 ssl_sock_free_ca(bind_conf);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008463 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008464 free(bind_conf->ca_file);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008465 free(bind_conf->ca_sign_file);
8466 free(bind_conf->ca_sign_pass);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008467 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02008468 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008469 free(bind_conf->crl_file);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008470 if(bind_conf->keys_ref) {
8471 free(bind_conf->keys_ref->filename);
8472 free(bind_conf->keys_ref->tlskeys);
8473 free(bind_conf->keys_ref);
8474 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008475#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008476 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008477
Willy Tarreau102df612014-05-07 23:56:38 +02008478 if (nbproc > 1) {
8479 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02008480 int count, maxproc = 0;
8481
8482 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
David Carliere6c39412015-07-02 07:00:17 +00008483 count = my_popcountl(bind_conf->bind_proc);
Willy Tarreaueb791e02014-09-16 15:11:04 +02008484 if (count > maxproc)
8485 maxproc = count;
8486 }
8487 /* backends have 0, frontends have 1 or more */
8488 if (maxproc != 1)
8489 Warning("Proxy '%s': in multi-process mode, stats will be"
8490 " limited to process assigned to the current request.\n",
8491 curproxy->id);
8492
Willy Tarreau102df612014-05-07 23:56:38 +02008493 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
8494 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
8495 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008496 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008497 }
Willy Tarreau102df612014-05-07 23:56:38 +02008498 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
8499 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
8500 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008501 }
8502 }
Willy Tarreau918ff602011-07-25 16:33:49 +02008503
8504 /* create the task associated with the proxy */
8505 curproxy->task = task_new();
8506 if (curproxy->task) {
8507 curproxy->task->context = curproxy;
8508 curproxy->task->process = manage_proxy;
8509 /* no need to queue, it will be done automatically if some
8510 * listener gets limited.
8511 */
8512 curproxy->task->expire = TICK_ETERNITY;
8513 } else {
8514 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
8515 curproxy->id);
8516 cfgerr++;
8517 }
Willy Tarreaub369a042014-09-16 13:21:03 +02008518 }
8519
Willy Tarreaufbb78422011-06-05 15:38:35 +02008520 /* automatically compute fullconn if not set. We must not do it in the
8521 * loop above because cross-references are not yet fully resolved.
8522 */
8523 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8524 /* If <fullconn> is not set, let's set it to 10% of the sum of
8525 * the possible incoming frontend's maxconns.
8526 */
8527 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
8528 struct proxy *fe;
8529 int total = 0;
8530
8531 /* sum up the number of maxconns of frontends which
8532 * reference this backend at least once or which are
8533 * the same one ('listen').
8534 */
8535 for (fe = proxy; fe; fe = fe->next) {
8536 struct switching_rule *rule;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008537 int found = 0;
8538
8539 if (!(fe->cap & PR_CAP_FE))
8540 continue;
8541
8542 if (fe == curproxy) /* we're on a "listen" instance */
8543 found = 1;
8544
8545 if (fe->defbe.be == curproxy) /* "default_backend" */
8546 found = 1;
8547
8548 /* check if a "use_backend" rule matches */
8549 if (!found) {
8550 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01008551 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02008552 found = 1;
8553 break;
8554 }
8555 }
8556 }
8557
Willy Tarreaufbb78422011-06-05 15:38:35 +02008558 /* now we've checked all possible ways to reference a backend
8559 * from a frontend.
8560 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02008561 if (!found)
8562 continue;
8563 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008564 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02008565 /* we have the sum of the maxconns in <total>. We only
8566 * keep 10% of that sum to set the default fullconn, with
8567 * a hard minimum of 1 (to avoid a divide by zero).
8568 */
8569 curproxy->fullconn = (total + 9) / 10;
8570 if (!curproxy->fullconn)
8571 curproxy->fullconn = 1;
8572 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01008573 }
8574
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008575 /*
8576 * Recount currently required checks.
8577 */
8578
8579 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
8580 int optnum;
8581
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008582 for (optnum = 0; cfg_opts[optnum].name; optnum++)
8583 if (curproxy->options & cfg_opts[optnum].val)
8584 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008585
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008586 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
8587 if (curproxy->options2 & cfg_opts2[optnum].val)
8588 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008589 }
8590
Willy Tarreau0fca4832015-05-01 19:12:05 +02008591 /* compute the required process bindings for the peers */
8592 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
8593 if (curproxy->table.peers.p)
8594 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
8595
Willy Tarreau122541c2011-09-07 21:24:49 +02008596 if (peers) {
8597 struct peers *curpeers = peers, **last;
8598 struct peer *p, *pb;
8599
Willy Tarreau1e273012015-05-01 19:15:17 +02008600 /* Remove all peers sections which don't have a valid listener,
8601 * which are not used by any table, or which are bound to more
8602 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02008603 */
8604 last = &peers;
8605 while (*last) {
8606 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008607
8608 if (curpeers->state == PR_STSTOPPED) {
8609 /* the "disabled" keyword was present */
8610 if (curpeers->peers_fe)
8611 stop_proxy(curpeers->peers_fe);
8612 curpeers->peers_fe = NULL;
8613 }
8614 else if (!curpeers->peers_fe) {
8615 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
8616 curpeers->id, localpeer);
8617 }
David Carliere6c39412015-07-02 07:00:17 +00008618 else if (my_popcountl(curpeers->peers_fe->bind_proc) != 1) {
Willy Tarreau1e273012015-05-01 19:15:17 +02008619 /* either it's totally stopped or too much used */
8620 if (curpeers->peers_fe->bind_proc) {
8621 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreau64c57222015-05-04 21:48:51 +02008622 "running in different processes (%d different ones). "
8623 "Check global.nbproc and all tables' bind-process "
David Carliere6c39412015-07-02 07:00:17 +00008624 "settings.\n", curpeers->id, my_popcountl(curpeers->peers_fe->bind_proc));
Willy Tarreau1e273012015-05-01 19:15:17 +02008625 cfgerr++;
8626 }
8627 stop_proxy(curpeers->peers_fe);
8628 curpeers->peers_fe = NULL;
8629 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008630 else {
Emeric Brunb3971ab2015-05-12 18:49:09 +02008631 peers_init_sync(curpeers);
Willy Tarreau122541c2011-09-07 21:24:49 +02008632 last = &curpeers->next;
8633 continue;
8634 }
8635
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008636 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02008637 p = curpeers->remote;
8638 while (p) {
8639 pb = p->next;
8640 free(p->id);
8641 free(p);
8642 p = pb;
8643 }
8644
8645 /* Destroy and unlink this curpeers section.
8646 * Note: curpeers is backed up into *last.
8647 */
8648 free(curpeers->id);
8649 curpeers = curpeers->next;
8650 free(*last);
8651 *last = curpeers;
8652 }
8653 }
8654
Willy Tarreau6866f3f2015-05-01 19:09:08 +02008655 /* initialize stick-tables on backend capable proxies. This must not
8656 * be done earlier because the data size may be discovered while parsing
8657 * other proxies.
8658 */
8659 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8660 if (curproxy->state == PR_STSTOPPED)
8661 continue;
8662
8663 if (!stktable_init(&curproxy->table)) {
8664 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
8665 cfgerr++;
8666 }
8667 }
8668
Simon Horman0d16a402015-01-30 11:22:58 +09008669 if (mailers) {
8670 struct mailers *curmailers = mailers, **last;
8671 struct mailer *m, *mb;
8672
8673 /* Remove all mailers sections which don't have a valid listener.
8674 * This can happen when a mailers section is never referenced.
8675 */
8676 last = &mailers;
8677 while (*last) {
8678 curmailers = *last;
8679 if (curmailers->users) {
8680 last = &curmailers->next;
8681 continue;
8682 }
8683
8684 Warning("Removing incomplete section 'mailers %s'.\n",
8685 curmailers->id);
8686
8687 m = curmailers->mailer_list;
8688 while (m) {
8689 mb = m->next;
8690 free(m->id);
8691 free(m);
8692 m = mb;
8693 }
8694
8695 /* Destroy and unlink this curmailers section.
8696 * Note: curmailers is backed up into *last.
8697 */
8698 free(curmailers->id);
8699 curmailers = curmailers->next;
8700 free(*last);
8701 *last = curmailers;
8702 }
8703 }
8704
Willy Tarreau34eb6712011-10-24 18:15:04 +02008705 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02008706 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02008707 MEM_F_SHARED);
8708
Willy Tarreaubb925012009-07-23 13:36:36 +02008709 if (cfgerr > 0)
8710 err_code |= ERR_ALERT | ERR_FATAL;
8711 out:
8712 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02008713}
8714
Willy Tarreau5b2c3362008-07-09 19:39:06 +02008715/*
8716 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
8717 * parsing sessions.
8718 */
8719void cfg_register_keywords(struct cfg_kw_list *kwl)
8720{
8721 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
8722}
Willy Tarreaubaaee002006-06-26 02:48:02 +02008723
Willy Tarreau5b2c3362008-07-09 19:39:06 +02008724/*
8725 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
8726 */
8727void cfg_unregister_keywords(struct cfg_kw_list *kwl)
8728{
8729 LIST_DEL(&kwl->list);
8730 LIST_INIT(&kwl->list);
8731}
Willy Tarreaubaaee002006-06-26 02:48:02 +02008732
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01008733/* this function register new section in the haproxy configuration file.
8734 * <section_name> is the name of this new section and <section_parser>
8735 * is the called parser. If two section declaration have the same name,
8736 * only the first declared is used.
8737 */
8738int cfg_register_section(char *section_name,
8739 int (*section_parser)(const char *, int, char **, int))
8740{
8741 struct cfg_section *cs;
8742
8743 cs = calloc(1, sizeof(*cs));
8744 if (!cs) {
8745 Alert("register section '%s': out of memory.\n", section_name);
8746 return 0;
8747 }
8748
8749 cs->section_name = section_name;
8750 cs->section_parser = section_parser;
8751
8752 LIST_ADDQ(&sections, &cs->list);
8753
8754 return 1;
8755}
8756
Willy Tarreaubaaee002006-06-26 02:48:02 +02008757/*
8758 * Local variables:
8759 * c-indent-level: 8
8760 * c-basic-offset: 8
8761 * End:
8762 */