blob: af2d7771fa32a6bd73564c1509193e200ed27ab6 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreauff011f22011-01-06 17:51:27 +01004 * Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
Cyril Bonté1a0191d2014-08-29 20:20:02 +020013#ifdef CONFIG_HAP_CRYPT
14/* This is to have crypt() defined on Linux */
15#define _GNU_SOURCE
16
17#ifdef NEED_CRYPT_H
18/* some platforms such as Solaris need this */
19#include <crypt.h>
20#endif
21#endif /* CONFIG_HAP_CRYPT */
22
Willy Tarreaubaaee002006-06-26 02:48:02 +020023#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <netdb.h>
27#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020028#include <pwd.h>
29#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020030#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020031#include <sys/types.h>
32#include <sys/stat.h>
33#include <fcntl.h>
34#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
Willy Tarreau2dd0d472006-06-29 17:53:05 +020036#include <common/cfgparse.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020037#include <common/chunk.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020038#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020039#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020040#include <common/memory.h>
41#include <common/standard.h>
42#include <common/time.h>
43#include <common/uri_auth.h>
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +010044#include <common/namespace.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020045
46#include <types/capture.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020047#include <types/compression.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020048#include <types/global.h>
Willy Tarreau3fdb3662012-11-12 00:42:33 +010049#include <types/obj_type.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020050#include <types/peers.h>
Simon Horman0d16a402015-01-30 11:22:58 +090051#include <types/mailers.h>
Baptiste Assmann325137d2015-04-13 23:40:55 +020052#include <types/dns.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020053
Willy Tarreaueb0c6142007-05-07 00:53:22 +020054#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010055#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020056#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020057#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020058#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020059#include <proto/compression.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020060#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020061#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020062#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020063#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010064#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020065#include <proto/lb_fwlc.h>
66#include <proto/lb_fwrr.h>
67#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020068#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020069#include <proto/log.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020070#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010071#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020072#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010073#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010074#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020075#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020076#include <proto/sample.h>
Willy Tarreau9903f0e2015-04-04 18:50:31 +020077#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020078#include <proto/server.h>
Willy Tarreau87b09662015-04-03 00:22:06 +020079#include <proto/stream.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020080#include <proto/raw_sock.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020081#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010082#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020083
Emeric Brunfc0421f2012-09-07 17:30:07 +020084#ifdef USE_OPENSSL
85#include <types/ssl_sock.h>
86#include <proto/ssl_sock.h>
87#include <proto/shctx.h>
88#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020089
Willy Tarreauf3c69202006-07-09 16:42:34 +020090/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
91 * ssl-hello-chk option to ensure that the remote server speaks SSL.
92 *
93 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
94 */
95const char sslv3_client_hello_pkt[] = {
96 "\x16" /* ContentType : 0x16 = Hanshake */
97 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
98 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
99 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
100 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
101 "\x03\x00" /* Hello Version : 0x0300 = v3 */
102 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
103 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
104 "\x00" /* Session ID length : empty (no session ID) */
105 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
106 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
107 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
108 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
109 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
110 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
111 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
112 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
113 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
114 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
115 "\x00\x38" "\x00\x39" "\x00\x3A"
116 "\x01" /* Compression Length : 0x01 = 1 byte for types */
117 "\x00" /* Compression Type : 0x00 = NULL compression */
118};
119
Willy Tarreau3842f002009-06-14 11:39:52 +0200120/* various keyword modifiers */
121enum kw_mod {
122 KWM_STD = 0, /* normal */
123 KWM_NO, /* "no" prefixed before the keyword */
124 KWM_DEF, /* "default" prefixed before the keyword */
125};
126
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +0100127/* permit to store configuration section */
128struct cfg_section {
129 struct list list;
130 char *section_name;
131 int (*section_parser)(const char *, int, char **, int);
132};
133
134/* Used to chain configuration sections definitions. This list
135 * stores struct cfg_section
136 */
137struct list sections = LIST_HEAD_INIT(sections);
138
Willy Tarreau13943ab2006-12-31 00:24:10 +0100139/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100140struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100141 const char *name;
142 unsigned int val;
143 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100144 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100145 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100146};
147
148/* proxy->options */
149static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100150{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100151 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
152 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
153 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
154 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
155 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
156 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100157 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau9fbe18e2015-05-01 22:42:08 +0200158 { "http-buffer-request", PR_O_WREQ_BODY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau0f228a02015-05-01 15:37:53 +0200159 { "http-ignore-probes", PR_O_IGNORE_PRB, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreau9420b122013-12-15 18:58:25 +0100160 { "prefer-last-server", PR_O_PREF_LAST, PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100161 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
162 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
163 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100164 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100165#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100166 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100167#else
168 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100169#endif
170
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100171 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100172};
173
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100174/* proxy->options2 */
175static const struct cfg_opt cfg_opts2[] =
176{
177#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100178 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
179 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
180 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100181#else
182 { "splice-request", 0, 0, 0, 0 },
183 { "splice-response", 0, 0, 0, 0 },
184 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100185#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100186 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
187 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
188 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
189 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
190 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
191 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
192 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
193 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
194 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400195 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100196 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200197 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200198 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100199 { NULL, 0, 0, 0 }
200};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200201
Willy Tarreau6daf3432008-01-22 16:44:08 +0100202static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200203static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
204int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100205int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200206
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200207/* List head of all known configuration keywords */
208static struct cfg_kw_list cfg_keywords = {
209 .list = LIST_HEAD_INIT(cfg_keywords.list)
210};
211
Willy Tarreaubaaee002006-06-26 02:48:02 +0200212/*
213 * converts <str> to a list of listeners which are dynamically allocated.
214 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
215 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
216 * - <port> is a numerical port from 1 to 65535 ;
217 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
218 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200219 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
220 * not NULL, it must be a valid pointer to either NULL or a freeable area that
221 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200222 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200223int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf, const char *file, int line, char **err)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200224{
225 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100226 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200227 int port, end;
228
229 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200230
Willy Tarreaubaaee002006-06-26 02:48:02 +0200231 while (next && *next) {
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100232 struct sockaddr_storage ss, *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100233 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200234
235 str = next;
236 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100237 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200238 *next++ = 0;
239 }
240
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100241 ss2 = str2sa_range(str, &port, &end, err,
Willy Tarreau72b8c1f2015-09-08 15:50:19 +0200242 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix,
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +0200243 NULL, 1);
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100244 if (!ss2)
245 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200246
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100247 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100248 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200249 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100250 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200251 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200252
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100253 if (!port || !end) {
254 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
255 goto fail;
256 }
257
Emeric Bruned760922010-10-22 17:59:25 +0200258 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200259 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200260 goto fail;
261 }
262
263 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200264 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200265 goto fail;
266 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200267 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100268 else if (ss2->ss_family == AF_UNSPEC) {
269 socklen_t addr_len;
270
271 /* We want to attach to an already bound fd whose number
272 * is in the addr part of ss2 when cast to sockaddr_in.
273 * Note that by definition there is a single listener.
274 * We still have to determine the address family to
275 * register the correct protocol.
276 */
277 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
278 addr_len = sizeof(*ss2);
279 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
280 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
281 goto fail;
282 }
283
284 port = end = get_host_port(ss2);
285 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200286
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100287 /* OK the address looks correct */
288 ss = *ss2;
289
Willy Tarreaubaaee002006-06-26 02:48:02 +0200290 for (; port <= end; port++) {
291 l = (struct listener *)calloc(1, sizeof(struct listener));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100292 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200293 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
294 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
295 l->frontend = curproxy;
296 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200297
Willy Tarreau40aa0702013-03-10 23:51:38 +0100298 l->fd = fd;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200299 l->addr = ss;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200300 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100301 l->state = LI_INIT;
302
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100303 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200304 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100305 tcpv4_add_listener(l);
306 }
Emeric Bruned760922010-10-22 17:59:25 +0200307 else if (ss.ss_family == AF_INET6) {
308 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
309 tcpv6_add_listener(l);
310 }
311 else {
Emeric Bruned760922010-10-22 17:59:25 +0200312 uxst_add_listener(l);
313 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200314
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200315 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100316 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200317 } /* end for(port) */
318 } /* end while(next) */
319 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200320 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200321 fail:
322 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200323 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200324}
325
William Lallemand6e62fb62015-04-28 16:55:23 +0200326/*
327 * Report a fatal Alert when there is too much arguments
328 * The index is the current keyword in args
329 * Return 0 if the number of argument is correct, otherwise emit an alert and return 1
330 * Fill err_code with an ERR_ALERT and an ERR_FATAL
331 */
332int alertif_too_many_args_idx(int maxarg, int index, const char *file, int linenum, char **args, int *err_code)
333{
334 char *kw = NULL;
335 int i;
336
337 if (!*args[index + maxarg + 1])
338 return 0;
339
340 memprintf(&kw, "%s", args[0]);
341 for (i = 1; i <= index; i++) {
342 memprintf(&kw, "%s %s", kw, args[i]);
343 }
344
345 Alert("parsing [%s:%d] : '%s' cannot handle unexpected argument '%s'.\n", file, linenum, kw, args[index + maxarg + 1]);
346 free(kw);
347 *err_code |= ERR_ALERT | ERR_FATAL;
348 return 1;
349}
350
351/*
352 * same as alertif_too_many_args_idx with a 0 index
353 */
354int alertif_too_many_args(int maxarg, const char *file, int linenum, char **args, int *err_code)
355{
356 return alertif_too_many_args_idx(maxarg, 0, file, linenum, args, err_code);
357}
358
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200359/* Report a warning if a rule is placed after a 'tcp-request content' rule.
360 * Return 1 if the warning has been emitted, otherwise 0.
361 */
362int warnif_rule_after_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
363{
364 if (!LIST_ISEMPTY(&proxy->tcp_req.inspect_rules)) {
365 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request content' rule will still be processed before.\n",
366 file, line, arg);
367 return 1;
368 }
369 return 0;
370}
371
Willy Tarreau61d18892009-03-31 10:49:21 +0200372/* Report a warning if a rule is placed after a 'block' rule.
373 * Return 1 if the warning has been emitted, otherwise 0.
374 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100375int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200376{
Willy Tarreau353bc9f2014-04-28 22:05:31 +0200377 if (!LIST_ISEMPTY(&proxy->block_rules)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200378 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
379 file, line, arg);
380 return 1;
381 }
382 return 0;
383}
384
Willy Tarreau5002f572014-04-23 01:32:02 +0200385/* Report a warning if a rule is placed after an 'http_request' rule.
386 * Return 1 if the warning has been emitted, otherwise 0.
387 */
388int warnif_rule_after_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
389{
390 if (!LIST_ISEMPTY(&proxy->http_req_rules)) {
391 Warning("parsing [%s:%d] : a '%s' rule placed after an 'http-request' rule will still be processed before.\n",
392 file, line, arg);
393 return 1;
394 }
395 return 0;
396}
397
Willy Tarreau61d18892009-03-31 10:49:21 +0200398/* Report a warning if a rule is placed after a reqrewrite rule.
399 * Return 1 if the warning has been emitted, otherwise 0.
400 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100401int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200402{
403 if (proxy->req_exp) {
404 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
405 file, line, arg);
406 return 1;
407 }
408 return 0;
409}
410
411/* Report a warning if a rule is placed after a reqadd rule.
412 * Return 1 if the warning has been emitted, otherwise 0.
413 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100414int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200415{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100416 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200417 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
418 file, line, arg);
419 return 1;
420 }
421 return 0;
422}
423
424/* Report a warning if a rule is placed after a redirect rule.
425 * Return 1 if the warning has been emitted, otherwise 0.
426 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100427int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200428{
429 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
430 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
431 file, line, arg);
432 return 1;
433 }
434 return 0;
435}
436
437/* Report a warning if a rule is placed after a 'use_backend' rule.
438 * Return 1 if the warning has been emitted, otherwise 0.
439 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100440int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200441{
442 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
443 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
444 file, line, arg);
445 return 1;
446 }
447 return 0;
448}
449
Willy Tarreauee445d92014-04-23 01:39:04 +0200450/* Report a warning if a rule is placed after a 'use-server' rule.
451 * Return 1 if the warning has been emitted, otherwise 0.
452 */
453int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line, const char *arg)
454{
455 if (!LIST_ISEMPTY(&proxy->server_rules)) {
456 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use-server' rule will still be processed before.\n",
457 file, line, arg);
458 return 1;
459 }
460 return 0;
461}
462
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200463/* report a warning if a "tcp request connection" rule is dangerously placed */
464int warnif_misplaced_tcp_conn(struct proxy *proxy, const char *file, int line, const char *arg)
465{
466 return warnif_rule_after_tcp_cont(proxy, file, line, arg) ||
467 warnif_rule_after_block(proxy, file, line, arg) ||
468 warnif_rule_after_http_req(proxy, file, line, arg) ||
469 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
470 warnif_rule_after_reqadd(proxy, file, line, arg) ||
471 warnif_rule_after_redirect(proxy, file, line, arg) ||
472 warnif_rule_after_use_backend(proxy, file, line, arg) ||
473 warnif_rule_after_use_server(proxy, file, line, arg);
474}
475
476/* report a warning if a "tcp request content" rule is dangerously placed */
477int warnif_misplaced_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
478{
479 return warnif_rule_after_block(proxy, file, line, arg) ||
480 warnif_rule_after_http_req(proxy, file, line, arg) ||
481 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
482 warnif_rule_after_reqadd(proxy, file, line, arg) ||
483 warnif_rule_after_redirect(proxy, file, line, arg) ||
484 warnif_rule_after_use_backend(proxy, file, line, arg) ||
485 warnif_rule_after_use_server(proxy, file, line, arg);
486}
487
Willy Tarreau61d18892009-03-31 10:49:21 +0200488/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100489int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200490{
Willy Tarreau5002f572014-04-23 01:32:02 +0200491 return warnif_rule_after_http_req(proxy, file, line, arg) ||
492 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
493 warnif_rule_after_reqadd(proxy, file, line, arg) ||
494 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200495 warnif_rule_after_use_backend(proxy, file, line, arg) ||
496 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau5002f572014-04-23 01:32:02 +0200497}
498
499/* report a warning if an http-request rule is dangerously placed */
500int warnif_misplaced_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
501{
Willy Tarreau61d18892009-03-31 10:49:21 +0200502 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
503 warnif_rule_after_reqadd(proxy, file, line, arg) ||
504 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200505 warnif_rule_after_use_backend(proxy, file, line, arg) ||
506 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200507}
508
509/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100510int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200511{
512 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
513 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200514 warnif_rule_after_use_backend(proxy, file, line, arg) ||
515 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200516}
517
518/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100519int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200520{
521 return warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200522 warnif_rule_after_use_backend(proxy, file, line, arg) ||
523 warnif_rule_after_use_server(proxy, file, line, arg);
524}
525
526/* report a warning if a redirect rule is dangerously placed */
527int warnif_misplaced_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
528{
529 return warnif_rule_after_use_backend(proxy, file, line, arg) ||
530 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200531}
532
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100533/* Report it if a request ACL condition uses some keywords that are incompatible
534 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
535 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
536 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100537 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100538static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100539{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100540 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200541 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100542
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100543 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100544 return 0;
545
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100546 acl = acl_cond_conflicts(cond, where);
547 if (acl) {
548 if (acl->name && *acl->name)
549 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
550 file, line, acl->name, sample_ckp_names(where));
551 else
552 Warning("parsing [%s:%d] : anonymous acl will never match because it uses keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200553 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100554 return ERR_WARN;
555 }
556 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100557 return 0;
558
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100559 if (acl->name && *acl->name)
560 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200561 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100562 else
563 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200564 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100565 return ERR_WARN;
566}
567
Willy Tarreaubaaee002006-06-26 02:48:02 +0200568/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200569 * parse a line in a <global> section. Returns the error code, 0 if OK, or
570 * any combination of :
571 * - ERR_ABORT: must abort ASAP
572 * - ERR_FATAL: we can continue parsing but not start the service
573 * - ERR_WARN: a warning has been emitted
574 * - ERR_ALERT: an alert has been emitted
575 * Only the two first ones can stop processing, the two others are just
576 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200577 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200578int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200579{
Willy Tarreau058e9072009-07-20 09:30:05 +0200580 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200581 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200582
583 if (!strcmp(args[0], "global")) { /* new section */
584 /* no option, nothing special to do */
William Lallemand6e62fb62015-04-28 16:55:23 +0200585 alertif_too_many_args(0, file, linenum, args, &err_code);
Willy Tarreau058e9072009-07-20 09:30:05 +0200586 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200587 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200588 else if (!strcmp(args[0], "ca-base")) {
589#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +0200590 if(alertif_too_many_args(1, file, linenum, args, &err_code))
591 goto out;
Emeric Brunc8e8d122012-10-02 18:42:10 +0200592 if (global.ca_base != NULL) {
593 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
594 err_code |= ERR_ALERT;
595 goto out;
596 }
597 if (*(args[1]) == 0) {
598 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
599 err_code |= ERR_ALERT | ERR_FATAL;
600 goto out;
601 }
602 global.ca_base = strdup(args[1]);
603#else
604 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
605 err_code |= ERR_ALERT | ERR_FATAL;
606 goto out;
607#endif
608 }
609 else if (!strcmp(args[0], "crt-base")) {
610#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +0200611 if (alertif_too_many_args(1, file, linenum, args, &err_code))
612 goto out;
Emeric Brunc8e8d122012-10-02 18:42:10 +0200613 if (global.crt_base != NULL) {
614 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
615 err_code |= ERR_ALERT;
616 goto out;
617 }
618 if (*(args[1]) == 0) {
619 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
620 err_code |= ERR_ALERT | ERR_FATAL;
621 goto out;
622 }
623 global.crt_base = strdup(args[1]);
624#else
625 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
626 err_code |= ERR_ALERT | ERR_FATAL;
627 goto out;
628#endif
629 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200630 else if (!strcmp(args[0], "daemon")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200631 if (alertif_too_many_args(0, file, linenum, args, &err_code))
632 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200633 global.mode |= MODE_DAEMON;
634 }
635 else if (!strcmp(args[0], "debug")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200636 if (alertif_too_many_args(0, file, linenum, args, &err_code))
637 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200638 global.mode |= MODE_DEBUG;
639 }
640 else if (!strcmp(args[0], "noepoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200641 if (alertif_too_many_args(0, file, linenum, args, &err_code))
642 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100643 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200644 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200645 else if (!strcmp(args[0], "nokqueue")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200646 if (alertif_too_many_args(0, file, linenum, args, &err_code))
647 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100648 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200649 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200650 else if (!strcmp(args[0], "nopoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200651 if (alertif_too_many_args(0, file, linenum, args, &err_code))
652 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100653 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200654 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100655 else if (!strcmp(args[0], "nosplice")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200656 if (alertif_too_many_args(0, file, linenum, args, &err_code))
657 goto out;
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100658 global.tune.options &= ~GTUNE_USE_SPLICE;
659 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200660 else if (!strcmp(args[0], "nogetaddrinfo")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200661 if (alertif_too_many_args(0, file, linenum, args, &err_code))
662 goto out;
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200663 global.tune.options &= ~GTUNE_USE_GAI;
664 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200665 else if (!strcmp(args[0], "quiet")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200666 if (alertif_too_many_args(0, file, linenum, args, &err_code))
667 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200668 global.mode |= MODE_QUIET;
669 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200670 else if (!strcmp(args[0], "tune.maxpollevents")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200671 if (alertif_too_many_args(1, file, linenum, args, &err_code))
672 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200673 if (global.tune.maxpollevents != 0) {
674 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200675 err_code |= ERR_ALERT;
676 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200677 }
678 if (*(args[1]) == 0) {
679 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200680 err_code |= ERR_ALERT | ERR_FATAL;
681 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200682 }
683 global.tune.maxpollevents = atol(args[1]);
684 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100685 else if (!strcmp(args[0], "tune.maxaccept")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200686 if (alertif_too_many_args(1, file, linenum, args, &err_code))
687 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100688 if (global.tune.maxaccept != 0) {
689 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200690 err_code |= ERR_ALERT;
691 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100692 }
693 if (*(args[1]) == 0) {
694 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200695 err_code |= ERR_ALERT | ERR_FATAL;
696 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100697 }
698 global.tune.maxaccept = atol(args[1]);
699 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200700 else if (!strcmp(args[0], "tune.chksize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200701 if (alertif_too_many_args(1, file, linenum, args, &err_code))
702 goto out;
Willy Tarreau43961d52010-10-04 20:39:20 +0200703 if (*(args[1]) == 0) {
704 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
705 err_code |= ERR_ALERT | ERR_FATAL;
706 goto out;
707 }
708 global.tune.chksize = atol(args[1]);
709 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200710#ifdef USE_OPENSSL
Emeric Brun8dc60392014-05-09 13:52:00 +0200711 else if (!strcmp(args[0], "tune.ssl.force-private-cache")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200712 if (alertif_too_many_args(0, file, linenum, args, &err_code))
713 goto out;
Emeric Brun8dc60392014-05-09 13:52:00 +0200714 global.tune.sslprivatecache = 1;
715 }
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100716 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200717 if (alertif_too_many_args(1, file, linenum, args, &err_code))
718 goto out;
Emeric Brunfc32aca2012-09-03 12:10:29 +0200719 if (*(args[1]) == 0) {
720 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
721 err_code |= ERR_ALERT | ERR_FATAL;
722 goto out;
723 }
724 global.tune.sslcachesize = atol(args[1]);
725 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100726 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
727 unsigned int ssllifetime;
728 const char *res;
729
William Lallemand1a748ae2015-05-19 16:37:23 +0200730 if (alertif_too_many_args(1, file, linenum, args, &err_code))
731 goto out;
Emeric Brun4f65bff2012-11-16 15:11:00 +0100732 if (*(args[1]) == 0) {
733 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
734 err_code |= ERR_ALERT | ERR_FATAL;
735 goto out;
736 }
737
738 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
739 if (res) {
740 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
741 file, linenum, *res, args[0]);
742 err_code |= ERR_ALERT | ERR_FATAL;
743 goto out;
744 }
745
746 global.tune.ssllifetime = ssllifetime;
747 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100748 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200749 if (alertif_too_many_args(1, file, linenum, args, &err_code))
750 goto out;
Willy Tarreaubfd59462013-02-21 07:46:09 +0100751 if (*(args[1]) == 0) {
752 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
753 err_code |= ERR_ALERT | ERR_FATAL;
754 goto out;
755 }
756 global.tune.ssl_max_record = atol(args[1]);
757 }
Remi Gacogne47783ef2015-05-29 15:53:22 +0200758#ifndef OPENSSL_NO_DH
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200759 else if (!strcmp(args[0], "tune.ssl.default-dh-param")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200760 if (alertif_too_many_args(1, file, linenum, args, &err_code))
761 goto out;
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200762 if (*(args[1]) == 0) {
763 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
764 err_code |= ERR_ALERT | ERR_FATAL;
765 goto out;
766 }
767 global.tune.ssl_default_dh_param = atol(args[1]);
768 if (global.tune.ssl_default_dh_param < 1024) {
769 Alert("parsing [%s:%d] : '%s' expects a value >= 1024.\n", file, linenum, args[0]);
770 err_code |= ERR_ALERT | ERR_FATAL;
771 goto out;
772 }
773 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200774#endif
Christopher Faulet31af49d2015-06-09 17:29:50 +0200775 else if (!strcmp(args[0], "tune.ssl.ssl-ctx-cache-size")) {
776 if (alertif_too_many_args(1, file, linenum, args, &err_code))
777 goto out;
778 if (*(args[1]) == 0) {
779 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
780 err_code |= ERR_ALERT | ERR_FATAL;
781 goto out;
782 }
783 global.tune.ssl_ctx_cache = atoi(args[1]);
784 if (global.tune.ssl_ctx_cache < 0) {
785 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
786 file, linenum, args[0]);
787 err_code |= ERR_ALERT | ERR_FATAL;
788 goto out;
789 }
790 }
Remi Gacogne47783ef2015-05-29 15:53:22 +0200791#endif
Willy Tarreau33cb0652014-12-23 22:52:37 +0100792 else if (!strcmp(args[0], "tune.buffers.limit")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200793 if (alertif_too_many_args(1, file, linenum, args, &err_code))
794 goto out;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100795 if (*(args[1]) == 0) {
796 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
797 err_code |= ERR_ALERT | ERR_FATAL;
798 goto out;
799 }
800 global.tune.buf_limit = atol(args[1]);
801 if (global.tune.buf_limit) {
802 if (global.tune.buf_limit < 3)
803 global.tune.buf_limit = 3;
804 if (global.tune.buf_limit <= global.tune.reserved_bufs)
805 global.tune.buf_limit = global.tune.reserved_bufs + 1;
806 }
807 }
Willy Tarreau1058ae72014-12-23 22:40:40 +0100808 else if (!strcmp(args[0], "tune.buffers.reserve")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200809 if (alertif_too_many_args(1, file, linenum, args, &err_code))
810 goto out;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100811 if (*(args[1]) == 0) {
812 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
813 err_code |= ERR_ALERT | ERR_FATAL;
814 goto out;
815 }
816 global.tune.reserved_bufs = atol(args[1]);
817 if (global.tune.reserved_bufs < 2)
818 global.tune.reserved_bufs = 2;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100819 if (global.tune.buf_limit && global.tune.buf_limit <= global.tune.reserved_bufs)
820 global.tune.buf_limit = global.tune.reserved_bufs + 1;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100821 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200822 else if (!strcmp(args[0], "tune.bufsize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200823 if (alertif_too_many_args(1, file, linenum, args, &err_code))
824 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200825 if (*(args[1]) == 0) {
826 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
827 err_code |= ERR_ALERT | ERR_FATAL;
828 goto out;
829 }
830 global.tune.bufsize = atol(args[1]);
Willy Tarreau9b694542015-09-28 13:49:53 +0200831 if (global.tune.bufsize <= 0) {
832 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
833 err_code |= ERR_ALERT | ERR_FATAL;
834 goto out;
835 }
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100836 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100837 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200838 }
839 else if (!strcmp(args[0], "tune.maxrewrite")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200840 if (alertif_too_many_args(1, file, linenum, args, &err_code))
841 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200842 if (*(args[1]) == 0) {
843 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
844 err_code |= ERR_ALERT | ERR_FATAL;
845 goto out;
846 }
847 global.tune.maxrewrite = atol(args[1]);
Willy Tarreau27097842015-09-28 13:53:23 +0200848 if (global.tune.maxrewrite < 0) {
849 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
850 err_code |= ERR_ALERT | ERR_FATAL;
851 goto out;
852 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200853 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100854 else if (!strcmp(args[0], "tune.idletimer")) {
855 unsigned int idle;
856 const char *res;
857
William Lallemand1a748ae2015-05-19 16:37:23 +0200858 if (alertif_too_many_args(1, file, linenum, args, &err_code))
859 goto out;
Willy Tarreau7e312732014-02-12 16:35:14 +0100860 if (*(args[1]) == 0) {
861 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
862 err_code |= ERR_ALERT | ERR_FATAL;
863 goto out;
864 }
865
866 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
867 if (res) {
868 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
869 file, linenum, *res, args[0]);
870 err_code |= ERR_ALERT | ERR_FATAL;
871 goto out;
872 }
873
874 if (idle > 65535) {
875 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
876 err_code |= ERR_ALERT | ERR_FATAL;
877 goto out;
878 }
879 global.tune.idle_timer = idle;
880 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100881 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200882 if (alertif_too_many_args(1, file, linenum, args, &err_code))
883 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100884 if (global.tune.client_rcvbuf != 0) {
885 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
886 err_code |= ERR_ALERT;
887 goto out;
888 }
889 if (*(args[1]) == 0) {
890 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
891 err_code |= ERR_ALERT | ERR_FATAL;
892 goto out;
893 }
894 global.tune.client_rcvbuf = atol(args[1]);
895 }
896 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200897 if (alertif_too_many_args(1, file, linenum, args, &err_code))
898 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100899 if (global.tune.server_rcvbuf != 0) {
900 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
901 err_code |= ERR_ALERT;
902 goto out;
903 }
904 if (*(args[1]) == 0) {
905 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
906 err_code |= ERR_ALERT | ERR_FATAL;
907 goto out;
908 }
909 global.tune.server_rcvbuf = atol(args[1]);
910 }
911 else if (!strcmp(args[0], "tune.sndbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200912 if (alertif_too_many_args(1, file, linenum, args, &err_code))
913 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100914 if (global.tune.client_sndbuf != 0) {
915 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
916 err_code |= ERR_ALERT;
917 goto out;
918 }
919 if (*(args[1]) == 0) {
920 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
921 err_code |= ERR_ALERT | ERR_FATAL;
922 goto out;
923 }
924 global.tune.client_sndbuf = atol(args[1]);
925 }
926 else if (!strcmp(args[0], "tune.sndbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200927 if (alertif_too_many_args(1, file, linenum, args, &err_code))
928 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100929 if (global.tune.server_sndbuf != 0) {
930 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
931 err_code |= ERR_ALERT;
932 goto out;
933 }
934 if (*(args[1]) == 0) {
935 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
936 err_code |= ERR_ALERT | ERR_FATAL;
937 goto out;
938 }
939 global.tune.server_sndbuf = atol(args[1]);
940 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200941 else if (!strcmp(args[0], "tune.pipesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200942 if (alertif_too_many_args(1, file, linenum, args, &err_code))
943 goto out;
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200944 if (*(args[1]) == 0) {
945 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
946 err_code |= ERR_ALERT | ERR_FATAL;
947 goto out;
948 }
949 global.tune.pipesize = atol(args[1]);
950 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100951 else if (!strcmp(args[0], "tune.http.cookielen")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200952 if (alertif_too_many_args(1, file, linenum, args, &err_code))
953 goto out;
Willy Tarreau193b8c62012-11-22 00:17:38 +0100954 if (*(args[1]) == 0) {
955 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
956 err_code |= ERR_ALERT | ERR_FATAL;
957 goto out;
958 }
959 global.tune.cookie_len = atol(args[1]) + 1;
960 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200961 else if (!strcmp(args[0], "tune.http.maxhdr")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200962 if (alertif_too_many_args(1, file, linenum, args, &err_code))
963 goto out;
Willy Tarreauac1932d2011-10-24 19:14:41 +0200964 if (*(args[1]) == 0) {
965 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
966 err_code |= ERR_ALERT | ERR_FATAL;
967 goto out;
968 }
969 global.tune.max_http_hdr = atol(args[1]);
970 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100971 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
972#ifdef USE_ZLIB
William Lallemand1a748ae2015-05-19 16:37:23 +0200973 if (alertif_too_many_args(1, file, linenum, args, &err_code))
974 goto out;
William Lallemanda509e4c2012-11-07 16:54:34 +0100975 if (*args[1]) {
976 global.tune.zlibmemlevel = atoi(args[1]);
977 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
978 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
979 file, linenum, args[0]);
980 err_code |= ERR_ALERT | ERR_FATAL;
981 goto out;
982 }
983 } else {
984 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
985 file, linenum, args[0]);
986 err_code |= ERR_ALERT | ERR_FATAL;
987 goto out;
988 }
989#else
990 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
991 err_code |= ERR_ALERT | ERR_FATAL;
992 goto out;
993#endif
994 }
995 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
996#ifdef USE_ZLIB
William Lallemand1a748ae2015-05-19 16:37:23 +0200997 if (alertif_too_many_args(1, file, linenum, args, &err_code))
998 goto out;
William Lallemanda509e4c2012-11-07 16:54:34 +0100999 if (*args[1]) {
1000 global.tune.zlibwindowsize = atoi(args[1]);
1001 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
1002 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
1003 file, linenum, args[0]);
1004 err_code |= ERR_ALERT | ERR_FATAL;
1005 goto out;
1006 }
1007 } else {
1008 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
1009 file, linenum, args[0]);
1010 err_code |= ERR_ALERT | ERR_FATAL;
1011 goto out;
1012 }
1013#else
1014 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1015 err_code |= ERR_ALERT | ERR_FATAL;
1016 goto out;
1017#endif
1018 }
William Lallemandf3747832012-11-09 12:33:10 +01001019 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001020 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1021 goto out;
William Lallemandf3747832012-11-09 12:33:10 +01001022 if (*args[1]) {
1023 global.tune.comp_maxlevel = atoi(args[1]);
1024 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
1025 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1026 file, linenum, args[0]);
1027 err_code |= ERR_ALERT | ERR_FATAL;
1028 goto out;
1029 }
1030 } else {
1031 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1032 file, linenum, args[0]);
1033 err_code |= ERR_ALERT | ERR_FATAL;
1034 goto out;
1035 }
1036 }
Willy Tarreauf3045d22015-04-29 16:24:50 +02001037 else if (!strcmp(args[0], "tune.pattern.cache-size")) {
1038 if (*args[1]) {
1039 global.tune.pattern_cache = atoi(args[1]);
1040 if (global.tune.pattern_cache < 0) {
1041 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
1042 file, linenum, args[0]);
1043 err_code |= ERR_ALERT | ERR_FATAL;
1044 goto out;
1045 }
1046 } else {
1047 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
1048 file, linenum, args[0]);
1049 err_code |= ERR_ALERT | ERR_FATAL;
1050 goto out;
1051 }
1052 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001053 else if (!strcmp(args[0], "uid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001054 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1055 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001056 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001057 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001058 err_code |= ERR_ALERT;
1059 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001060 }
1061 if (*(args[1]) == 0) {
1062 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001063 err_code |= ERR_ALERT | ERR_FATAL;
1064 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001065 }
1066 global.uid = atol(args[1]);
1067 }
1068 else if (!strcmp(args[0], "gid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001069 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1070 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001071 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001072 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001073 err_code |= ERR_ALERT;
1074 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001075 }
1076 if (*(args[1]) == 0) {
1077 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001078 err_code |= ERR_ALERT | ERR_FATAL;
1079 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001080 }
1081 global.gid = atol(args[1]);
1082 }
Simon Horman98637e52014-06-20 12:30:16 +09001083 else if (!strcmp(args[0], "external-check")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001084 if (alertif_too_many_args(0, file, linenum, args, &err_code))
1085 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09001086 global.external_check = 1;
1087 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001088 /* user/group name handling */
1089 else if (!strcmp(args[0], "user")) {
1090 struct passwd *ha_user;
William Lallemand1a748ae2015-05-19 16:37:23 +02001091 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1092 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001093 if (global.uid != 0) {
1094 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001095 err_code |= ERR_ALERT;
1096 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001097 }
1098 errno = 0;
1099 ha_user = getpwnam(args[1]);
1100 if (ha_user != NULL) {
1101 global.uid = (int)ha_user->pw_uid;
1102 }
1103 else {
1104 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +02001105 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001106 }
1107 }
1108 else if (!strcmp(args[0], "group")) {
1109 struct group *ha_group;
William Lallemand1a748ae2015-05-19 16:37:23 +02001110 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1111 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001112 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02001113 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001114 err_code |= ERR_ALERT;
1115 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001116 }
1117 errno = 0;
1118 ha_group = getgrnam(args[1]);
1119 if (ha_group != NULL) {
1120 global.gid = (int)ha_group->gr_gid;
1121 }
1122 else {
1123 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +02001124 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001125 }
1126 }
1127 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +02001128 else if (!strcmp(args[0], "nbproc")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001129 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1130 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001131 if (*(args[1]) == 0) {
1132 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001133 err_code |= ERR_ALERT | ERR_FATAL;
1134 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001135 }
1136 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001137 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
1138 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
1139 file, linenum, args[0], LONGBITS, global.nbproc);
1140 err_code |= ERR_ALERT | ERR_FATAL;
1141 goto out;
1142 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001143 }
1144 else if (!strcmp(args[0], "maxconn")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001145 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1146 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001147 if (global.maxconn != 0) {
1148 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001149 err_code |= ERR_ALERT;
1150 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001151 }
1152 if (*(args[1]) == 0) {
1153 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001154 err_code |= ERR_ALERT | ERR_FATAL;
1155 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001156 }
1157 global.maxconn = atol(args[1]);
1158#ifdef SYSTEM_MAXCONN
1159 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
1160 Alert("parsing [%s:%d] : maxconn value %d too high for this system.\nLimiting to %d. Please use '-n' to force the value.\n", file, linenum, global.maxconn, DEFAULT_MAXCONN);
1161 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +02001162 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001163 }
1164#endif /* SYSTEM_MAXCONN */
1165 }
Willy Tarreau403edff2012-09-06 11:58:37 +02001166 else if (!strcmp(args[0], "maxsslconn")) {
1167#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001168 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1169 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001170 if (*(args[1]) == 0) {
1171 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1172 err_code |= ERR_ALERT | ERR_FATAL;
1173 goto out;
1174 }
1175 global.maxsslconn = atol(args[1]);
1176#else
Emeric Brun0914df82012-10-02 18:45:42 +02001177 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1178 err_code |= ERR_ALERT | ERR_FATAL;
1179 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001180#endif
1181 }
Willy Tarreau610f04b2014-02-13 11:36:41 +01001182 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
1183#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001184 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1185 goto out;
Willy Tarreau610f04b2014-02-13 11:36:41 +01001186 if (*(args[1]) == 0) {
1187 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1188 err_code |= ERR_ALERT | ERR_FATAL;
1189 goto out;
1190 }
1191 free(global.listen_default_ciphers);
1192 global.listen_default_ciphers = strdup(args[1]);
1193#else
1194 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1195 err_code |= ERR_ALERT | ERR_FATAL;
1196 goto out;
1197#endif
1198 }
1199 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
1200#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001201 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1202 goto out;
Willy Tarreau610f04b2014-02-13 11:36:41 +01001203 if (*(args[1]) == 0) {
1204 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1205 err_code |= ERR_ALERT | ERR_FATAL;
1206 goto out;
1207 }
1208 free(global.connect_default_ciphers);
1209 global.connect_default_ciphers = strdup(args[1]);
1210#else
1211 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1212 err_code |= ERR_ALERT | ERR_FATAL;
1213 goto out;
1214#endif
1215 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02001216#ifdef USE_OPENSSL
1217#ifndef OPENSSL_NO_DH
1218 else if (!strcmp(args[0], "ssl-dh-param-file")) {
1219 if (*(args[1]) == 0) {
1220 Alert("parsing [%s:%d] : '%s' expects a file path as an argument.\n", file, linenum, args[0]);
1221 err_code |= ERR_ALERT | ERR_FATAL;
1222 goto out;
1223 }
1224 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
1225 Alert("parsing [%s:%d] : '%s': unable to load DH parameters from file <%s>.\n", file, linenum, args[0], args[1]);
1226 err_code |= ERR_ALERT | ERR_FATAL;
1227 goto out;
1228 }
1229 }
1230#endif
1231#endif
Emeric Brun850efd52014-01-29 12:24:34 +01001232 else if (!strcmp(args[0], "ssl-server-verify")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001233 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1234 goto out;
Emeric Brun850efd52014-01-29 12:24:34 +01001235 if (*(args[1]) == 0) {
1236 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1237 err_code |= ERR_ALERT | ERR_FATAL;
1238 goto out;
1239 }
1240 if (strcmp(args[1],"none") == 0)
1241 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1242 else if (strcmp(args[1],"required") == 0)
1243 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1244 else {
1245 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1246 err_code |= ERR_ALERT | ERR_FATAL;
1247 goto out;
1248 }
1249 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001250 else if (!strcmp(args[0], "maxconnrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001251 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1252 goto out;
Willy Tarreau81c25d02011-09-07 15:17:21 +02001253 if (global.cps_lim != 0) {
1254 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1255 err_code |= ERR_ALERT;
1256 goto out;
1257 }
1258 if (*(args[1]) == 0) {
1259 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1260 err_code |= ERR_ALERT | ERR_FATAL;
1261 goto out;
1262 }
1263 global.cps_lim = atol(args[1]);
1264 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001265 else if (!strcmp(args[0], "maxsessrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001266 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1267 goto out;
Willy Tarreau93e7c002013-10-07 18:51:07 +02001268 if (global.sps_lim != 0) {
1269 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1270 err_code |= ERR_ALERT;
1271 goto out;
1272 }
1273 if (*(args[1]) == 0) {
1274 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1275 err_code |= ERR_ALERT | ERR_FATAL;
1276 goto out;
1277 }
1278 global.sps_lim = atol(args[1]);
1279 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001280 else if (!strcmp(args[0], "maxsslrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001281 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1282 goto out;
Willy Tarreaue43d5322013-10-07 20:01:52 +02001283 if (global.ssl_lim != 0) {
1284 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1285 err_code |= ERR_ALERT;
1286 goto out;
1287 }
1288 if (*(args[1]) == 0) {
1289 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1290 err_code |= ERR_ALERT | ERR_FATAL;
1291 goto out;
1292 }
1293 global.ssl_lim = atol(args[1]);
1294 }
William Lallemandd85f9172012-11-09 17:05:39 +01001295 else if (!strcmp(args[0], "maxcomprate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001296 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1297 goto out;
William Lallemandd85f9172012-11-09 17:05:39 +01001298 if (*(args[1]) == 0) {
1299 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1300 err_code |= ERR_ALERT | ERR_FATAL;
1301 goto out;
1302 }
1303 global.comp_rate_lim = atoi(args[1]) * 1024;
1304 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001305 else if (!strcmp(args[0], "maxpipes")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001306 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1307 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001308 if (global.maxpipes != 0) {
1309 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001310 err_code |= ERR_ALERT;
1311 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001312 }
1313 if (*(args[1]) == 0) {
1314 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001315 err_code |= ERR_ALERT | ERR_FATAL;
1316 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001317 }
1318 global.maxpipes = atol(args[1]);
1319 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001320 else if (!strcmp(args[0], "maxzlibmem")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001321 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1322 goto out;
William Lallemand9d5f5482012-11-07 16:12:57 +01001323 if (*(args[1]) == 0) {
1324 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1325 err_code |= ERR_ALERT | ERR_FATAL;
1326 goto out;
1327 }
William Lallemande3a7d992012-11-20 11:25:20 +01001328 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001329 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001330 else if (!strcmp(args[0], "maxcompcpuusage")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001331 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1332 goto out;
William Lallemand072a2bf2012-11-20 17:01:01 +01001333 if (*(args[1]) == 0) {
1334 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1335 err_code |= ERR_ALERT | ERR_FATAL;
1336 goto out;
1337 }
1338 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001339 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001340 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1341 err_code |= ERR_ALERT | ERR_FATAL;
1342 goto out;
1343 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001344 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001345
Willy Tarreaubaaee002006-06-26 02:48:02 +02001346 else if (!strcmp(args[0], "ulimit-n")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001347 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1348 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001349 if (global.rlimit_nofile != 0) {
1350 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001351 err_code |= ERR_ALERT;
1352 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001353 }
1354 if (*(args[1]) == 0) {
1355 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001356 err_code |= ERR_ALERT | ERR_FATAL;
1357 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001358 }
1359 global.rlimit_nofile = atol(args[1]);
1360 }
1361 else if (!strcmp(args[0], "chroot")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001362 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1363 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001364 if (global.chroot != NULL) {
1365 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001366 err_code |= ERR_ALERT;
1367 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001368 }
1369 if (*(args[1]) == 0) {
1370 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001371 err_code |= ERR_ALERT | ERR_FATAL;
1372 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001373 }
1374 global.chroot = strdup(args[1]);
1375 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001376 else if (!strcmp(args[0], "description")) {
1377 int i, len=0;
1378 char *d;
1379
1380 if (!*args[1]) {
1381 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1382 file, linenum, args[0]);
1383 err_code |= ERR_ALERT | ERR_FATAL;
1384 goto out;
1385 }
1386
Willy Tarreau348acfe2014-04-14 15:00:39 +02001387 for (i = 1; *args[i]; i++)
1388 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001389
1390 if (global.desc)
1391 free(global.desc);
1392
1393 global.desc = d = (char *)calloc(1, len);
1394
Willy Tarreau348acfe2014-04-14 15:00:39 +02001395 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1396 for (i = 2; *args[i]; i++)
1397 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001398 }
1399 else if (!strcmp(args[0], "node")) {
1400 int i;
1401 char c;
1402
William Lallemand1a748ae2015-05-19 16:37:23 +02001403 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1404 goto out;
1405
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001406 for (i=0; args[1][i]; i++) {
1407 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001408 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1409 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001410 break;
1411 }
1412
1413 if (!i || args[1][i]) {
1414 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1415 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1416 file, linenum, args[0]);
1417 err_code |= ERR_ALERT | ERR_FATAL;
1418 goto out;
1419 }
1420
1421 if (global.node)
1422 free(global.node);
1423
1424 global.node = strdup(args[1]);
1425 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001426 else if (!strcmp(args[0], "pidfile")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001427 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1428 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001429 if (global.pidfile != NULL) {
1430 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001431 err_code |= ERR_ALERT;
1432 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001433 }
1434 if (*(args[1]) == 0) {
1435 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001436 err_code |= ERR_ALERT | ERR_FATAL;
1437 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001438 }
1439 global.pidfile = strdup(args[1]);
1440 }
Emeric Bruned760922010-10-22 17:59:25 +02001441 else if (!strcmp(args[0], "unix-bind")) {
1442 int cur_arg = 1;
1443 while (*(args[cur_arg])) {
1444 if (!strcmp(args[cur_arg], "prefix")) {
1445 if (global.unix_bind.prefix != NULL) {
1446 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1447 err_code |= ERR_ALERT;
1448 cur_arg += 2;
1449 continue;
1450 }
1451
1452 if (*(args[cur_arg+1]) == 0) {
1453 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1454 err_code |= ERR_ALERT | ERR_FATAL;
1455 goto out;
1456 }
1457 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1458 cur_arg += 2;
1459 continue;
1460 }
1461
1462 if (!strcmp(args[cur_arg], "mode")) {
1463
1464 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1465 cur_arg += 2;
1466 continue;
1467 }
1468
1469 if (!strcmp(args[cur_arg], "uid")) {
1470
1471 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1472 cur_arg += 2;
1473 continue;
1474 }
1475
1476 if (!strcmp(args[cur_arg], "gid")) {
1477
1478 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1479 cur_arg += 2;
1480 continue;
1481 }
1482
1483 if (!strcmp(args[cur_arg], "user")) {
1484 struct passwd *user;
1485
1486 user = getpwnam(args[cur_arg + 1]);
1487 if (!user) {
1488 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1489 file, linenum, args[0], args[cur_arg + 1 ]);
1490 err_code |= ERR_ALERT | ERR_FATAL;
1491 goto out;
1492 }
1493
1494 global.unix_bind.ux.uid = user->pw_uid;
1495 cur_arg += 2;
1496 continue;
1497 }
1498
1499 if (!strcmp(args[cur_arg], "group")) {
1500 struct group *group;
1501
1502 group = getgrnam(args[cur_arg + 1]);
1503 if (!group) {
1504 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1505 file, linenum, args[0], args[cur_arg + 1 ]);
1506 err_code |= ERR_ALERT | ERR_FATAL;
1507 goto out;
1508 }
1509
1510 global.unix_bind.ux.gid = group->gr_gid;
1511 cur_arg += 2;
1512 continue;
1513 }
1514
Willy Tarreaub48f9582011-09-05 01:17:06 +02001515 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001516 file, linenum, args[0]);
1517 err_code |= ERR_ALERT | ERR_FATAL;
1518 goto out;
1519 }
1520 }
William Lallemand0f99e342011-10-12 17:50:54 +02001521 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1522 /* delete previous herited or defined syslog servers */
1523 struct logsrv *back;
1524 struct logsrv *tmp;
1525
1526 if (*(args[1]) != 0) {
1527 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1528 err_code |= ERR_ALERT | ERR_FATAL;
1529 goto out;
1530 }
1531
1532 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1533 LIST_DEL(&tmp->list);
1534 free(tmp);
1535 }
1536 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001537 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001538 struct sockaddr_storage *sk;
1539 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001540 struct logsrv *logsrv;
Willy Tarreau18324f52014-06-27 18:10:07 +02001541 int arg = 0;
1542 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001543
William Lallemand1a748ae2015-05-19 16:37:23 +02001544 if (alertif_too_many_args(8, file, linenum, args, &err_code)) /* does not strictly check optional arguments */
1545 goto out;
1546
Willy Tarreaubaaee002006-06-26 02:48:02 +02001547 if (*(args[1]) == 0 || *(args[2]) == 0) {
1548 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001549 err_code |= ERR_ALERT | ERR_FATAL;
1550 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001551 }
William Lallemand0f99e342011-10-12 17:50:54 +02001552
1553 logsrv = calloc(1, sizeof(struct logsrv));
1554
Willy Tarreau18324f52014-06-27 18:10:07 +02001555 /* just after the address, a length may be specified */
1556 if (strcmp(args[arg+2], "len") == 0) {
1557 len = atoi(args[arg+3]);
1558 if (len < 80 || len > 65535) {
1559 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1560 file, linenum, args[arg+3]);
1561 err_code |= ERR_ALERT | ERR_FATAL;
1562 goto out;
1563 }
1564 logsrv->maxlen = len;
1565
1566 /* skip these two args */
1567 arg += 2;
1568 }
1569 else
1570 logsrv->maxlen = MAX_SYSLOG_LEN;
1571
1572 if (logsrv->maxlen > global.max_syslog_len) {
1573 global.max_syslog_len = logsrv->maxlen;
Dragan Dosen59cee972015-09-19 22:09:02 +02001574 logheader = realloc(logheader, global.max_syslog_len + 1);
Dragan Dosen1322d092015-09-22 16:05:32 +02001575 logheader_rfc5424 = realloc(logheader_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02001576 logline = realloc(logline, global.max_syslog_len + 1);
1577 }
1578
Dragan Dosen1322d092015-09-22 16:05:32 +02001579 /* after the length, a format may be specified */
1580 if (strcmp(args[arg+2], "format") == 0) {
1581 logsrv->format = get_log_format(args[arg+3]);
1582 if (logsrv->format < 0) {
1583 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
1584 err_code |= ERR_ALERT | ERR_FATAL;
1585 goto out;
1586 }
1587
1588 /* skip these two args */
1589 arg += 2;
1590 }
1591
William Lallemand1a748ae2015-05-19 16:37:23 +02001592 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
1593 goto out;
1594
Willy Tarreau18324f52014-06-27 18:10:07 +02001595 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001596 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001597 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001598 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001599 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001600 }
1601
William Lallemand0f99e342011-10-12 17:50:54 +02001602 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02001603 if (*(args[arg+3])) {
1604 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001605 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001606 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001607 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001608 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001609 }
1610 }
1611
William Lallemand0f99e342011-10-12 17:50:54 +02001612 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02001613 if (*(args[arg+4])) {
1614 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001615 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001616 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001617 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001618 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001619 }
1620 }
1621
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02001622 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001623 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001624 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001625 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001626 free(logsrv);
1627 goto out;
1628 }
1629 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001630
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001631 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001632 if (port1 != port2) {
1633 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1634 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001635 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001636 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001637 goto out;
1638 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001639
William Lallemand0f99e342011-10-12 17:50:54 +02001640 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001641 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001642 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001643 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001644
William Lallemand0f99e342011-10-12 17:50:54 +02001645 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001646 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001647 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1648 char *name;
1649 int len;
1650
1651 if (global.log_send_hostname != NULL) {
1652 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1653 err_code |= ERR_ALERT;
1654 goto out;
1655 }
1656
1657 if (*(args[1]))
1658 name = args[1];
1659 else
1660 name = hostname;
1661
1662 len = strlen(name);
1663
1664 /* We'll add a space after the name to respect the log format */
1665 free(global.log_send_hostname);
1666 global.log_send_hostname = malloc(len + 2);
1667 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1668 }
Baptiste Assmann6bc89362015-08-23 09:22:25 +02001669 else if (!strcmp(args[0], "server-state-base")) { /* path base where HAProxy can find server state files */
1670 if (global.server_state_base != NULL) {
1671 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1672 err_code |= ERR_ALERT;
1673 goto out;
1674 }
1675
1676 if (!*(args[1])) {
1677 Alert("parsing [%s:%d] : '%s' expects one argument: a directory path.\n", file, linenum, args[0]);
1678 err_code |= ERR_FATAL;
1679 goto out;
1680 }
1681
1682 global.server_state_base = strdup(args[1]);
1683 }
Baptiste Assmanne0882262015-08-23 09:54:31 +02001684 else if (!strcmp(args[0], "server-state-file")) { /* path to the file where HAProxy can load the server states */
1685 if (global.server_state_file != NULL) {
1686 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1687 err_code |= ERR_ALERT;
1688 goto out;
1689 }
1690
1691 if (!*(args[1])) {
1692 Alert("parsing [%s:%d] : '%s' expect one argument: a file path.\n", file, linenum, args[0]);
1693 err_code |= ERR_FATAL;
1694 goto out;
1695 }
1696
1697 global.server_state_file = strdup(args[1]);
1698 }
Kevinm48936af2010-12-22 16:08:21 +00001699 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
William Lallemand1a748ae2015-05-19 16:37:23 +02001700 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1701 goto out;
Kevinm48936af2010-12-22 16:08:21 +00001702 if (*(args[1]) == 0) {
1703 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1704 err_code |= ERR_ALERT | ERR_FATAL;
1705 goto out;
1706 }
1707 free(global.log_tag);
1708 global.log_tag = strdup(args[1]);
1709 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001710 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
William Lallemand1a748ae2015-05-19 16:37:23 +02001711 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1712 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001713 if (global.spread_checks != 0) {
1714 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001715 err_code |= ERR_ALERT;
1716 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001717 }
1718 if (*(args[1]) == 0) {
1719 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001720 err_code |= ERR_ALERT | ERR_FATAL;
1721 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001722 }
1723 global.spread_checks = atol(args[1]);
1724 if (global.spread_checks < 0 || global.spread_checks > 50) {
1725 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001726 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001727 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001728 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001729 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1730 const char *err;
1731 unsigned int val;
1732
William Lallemand1a748ae2015-05-19 16:37:23 +02001733 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1734 goto out;
Willy Tarreau1746eec2014-04-25 10:46:47 +02001735 if (*(args[1]) == 0) {
1736 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1737 err_code |= ERR_ALERT | ERR_FATAL;
1738 goto out;
1739 }
1740
1741 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1742 if (err) {
1743 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1744 err_code |= ERR_ALERT | ERR_FATAL;
1745 }
1746 global.max_spread_checks = val;
1747 if (global.max_spread_checks < 0) {
1748 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1749 err_code |= ERR_ALERT | ERR_FATAL;
1750 }
1751 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001752 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1753#ifdef USE_CPU_AFFINITY
1754 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001755 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001756 unsigned long cpus = 0;
1757
1758 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001759 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001760 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001761 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001762 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001763 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001764 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001765 proc = atol(args[1]);
1766 if (proc >= 1 && proc <= LONGBITS)
1767 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001768 }
1769
1770 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001771 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",
1772 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001773 err_code |= ERR_ALERT | ERR_FATAL;
1774 goto out;
1775 }
1776
1777 cur_arg = 2;
1778 while (*args[cur_arg]) {
1779 unsigned int low, high;
1780
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001781 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001782 char *dash = strchr(args[cur_arg], '-');
1783
1784 low = high = str2uic(args[cur_arg]);
1785 if (dash)
1786 high = str2uic(dash + 1);
1787
1788 if (high < low) {
1789 unsigned int swap = low;
1790 low = high;
1791 high = swap;
1792 }
1793
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001794 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001795 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001796 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001797 err_code |= ERR_ALERT | ERR_FATAL;
1798 goto out;
1799 }
1800
1801 while (low <= high)
1802 cpus |= 1UL << low++;
1803 }
1804 else {
1805 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1806 file, linenum, args[0], args[cur_arg]);
1807 err_code |= ERR_ALERT | ERR_FATAL;
1808 goto out;
1809 }
1810 cur_arg++;
1811 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001812 for (i = 0; i < LONGBITS; i++)
1813 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001814 global.cpu_map[i] = cpus;
1815#else
1816 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1817 err_code |= ERR_ALERT | ERR_FATAL;
1818 goto out;
1819#endif
1820 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001821 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001822 struct cfg_kw_list *kwl;
1823 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001824 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001825
1826 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1827 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1828 if (kwl->kw[index].section != CFG_GLOBAL)
1829 continue;
1830 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001831 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001832 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001833 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001834 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001835 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001836 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001837 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001838 err_code |= ERR_WARN;
1839 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001840 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001841 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001842 }
1843 }
1844 }
1845
Willy Tarreaubaaee002006-06-26 02:48:02 +02001846 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001847 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001848 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001849
Willy Tarreau058e9072009-07-20 09:30:05 +02001850 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001851 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001852 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001853}
1854
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001855void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001856{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001857 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001858 defproxy.mode = PR_MODE_TCP;
1859 defproxy.state = PR_STNEW;
1860 defproxy.maxconn = cfg_maxpconn;
1861 defproxy.conn_retries = CONN_RETRIES;
Joseph Lynch726ab712015-05-11 23:25:34 -07001862 defproxy.redispatch_after = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001863
Simon Horman66183002013-02-23 10:16:43 +09001864 defproxy.defsrv.check.inter = DEF_CHKINTR;
1865 defproxy.defsrv.check.fastinter = 0;
1866 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001867 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1868 defproxy.defsrv.agent.fastinter = 0;
1869 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001870 defproxy.defsrv.check.rise = DEF_RISETIME;
1871 defproxy.defsrv.check.fall = DEF_FALLTIME;
1872 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1873 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001874 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001875 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001876 defproxy.defsrv.maxqueue = 0;
1877 defproxy.defsrv.minconn = 0;
1878 defproxy.defsrv.maxconn = 0;
1879 defproxy.defsrv.slowstart = 0;
1880 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1881 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1882 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Simon Horman64e34162015-02-06 11:11:57 +09001883
1884 defproxy.email_alert.level = LOG_ALERT;
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02001885 defproxy.load_server_state_from_file = PR_SRV_STATE_FILE_UNSPEC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001886}
1887
Willy Tarreauade5ec42010-01-28 19:33:49 +01001888
Willy Tarreau63af98d2014-05-18 08:11:41 +02001889/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1890 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1891 * ERR_FATAL in case of error.
1892 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001893static int create_cond_regex_rule(const char *file, int line,
1894 struct proxy *px, int dir, int action, int flags,
1895 const char *cmd, const char *reg, const char *repl,
1896 const char **cond_start)
1897{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001898 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001899 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001900 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001901 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001902 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001903 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001904 int cs;
1905 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001906
1907 if (px == &defproxy) {
1908 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001909 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001910 goto err;
1911 }
1912
1913 if (*reg == 0) {
1914 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001915 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001916 goto err;
1917 }
1918
1919 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001920 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001921
Willy Tarreau5321c422010-01-28 20:35:13 +01001922 if (cond_start &&
1923 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001924 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1925 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1926 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001927 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001928 goto err;
1929 }
1930 }
1931 else if (cond_start && **cond_start) {
1932 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1933 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001934 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001935 goto err;
1936 }
1937
Willy Tarreau63af98d2014-05-18 08:11:41 +02001938 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001939 (dir == SMP_OPT_DIR_REQ) ?
1940 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1941 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1942 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001943
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001944 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001945 if (!preg) {
1946 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001947 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001948 goto err;
1949 }
1950
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001951 cs = !(flags & REG_ICASE);
1952 cap = !(flags & REG_NOSUB);
1953 error = NULL;
1954 if (!regex_comp(reg, preg, cs, cap, &error)) {
1955 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1956 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001957 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001958 goto err;
1959 }
1960
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001961 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001962 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001963 if (repl && err) {
1964 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1965 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001966 ret_code |= ERR_ALERT | ERR_FATAL;
1967 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001968 }
1969
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001970 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001971 ret_code |= ERR_WARN;
1972
1973 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001974
Willy Tarreau63af98d2014-05-18 08:11:41 +02001975 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001976 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001977 err:
1978 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001979 free(errmsg);
1980 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001981}
1982
Willy Tarreaubaaee002006-06-26 02:48:02 +02001983/*
William Lallemand51097192015-04-14 16:35:22 +02001984 * Parse a line in a <listen>, <frontend> or <backend> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001985 * Returns the error code, 0 if OK, or any combination of :
1986 * - ERR_ABORT: must abort ASAP
1987 * - ERR_FATAL: we can continue parsing but not start the service
1988 * - ERR_WARN: a warning has been emitted
1989 * - ERR_ALERT: an alert has been emitted
1990 * Only the two first ones can stop processing, the two others are just
1991 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001992 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001993int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1994{
1995 static struct peers *curpeers = NULL;
1996 struct peer *newpeer = NULL;
1997 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001998 struct bind_conf *bind_conf;
1999 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02002000 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01002001 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02002002
2003 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002004 if (!*args[1]) {
2005 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01002006 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002007 goto out;
2008 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002009
William Lallemand6e62fb62015-04-28 16:55:23 +02002010 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2011 goto out;
2012
Emeric Brun32da3c42010-09-23 18:39:19 +02002013 err = invalid_char(args[1]);
2014 if (err) {
2015 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2016 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01002017 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002018 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002019 }
2020
2021 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
2022 /*
2023 * If there are two proxies with the same name only following
2024 * combinations are allowed:
2025 */
2026 if (strcmp(curpeers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002027 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 +02002028 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002029 err_code |= ERR_ALERT | ERR_FATAL;
Emeric Brun32da3c42010-09-23 18:39:19 +02002030 }
2031 }
2032
2033 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
2034 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2035 err_code |= ERR_ALERT | ERR_ABORT;
2036 goto out;
2037 }
2038
2039 curpeers->next = peers;
2040 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002041 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002042 curpeers->conf.line = linenum;
2043 curpeers->last_change = now.tv_sec;
2044 curpeers->id = strdup(args[1]);
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002045 curpeers->state = PR_STNEW;
Emeric Brun32da3c42010-09-23 18:39:19 +02002046 }
2047 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01002048 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01002049 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002050 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02002051
2052 if (!*args[2]) {
2053 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2054 file, linenum, args[0]);
2055 err_code |= ERR_ALERT | ERR_FATAL;
2056 goto out;
2057 }
2058
2059 err = invalid_char(args[1]);
2060 if (err) {
2061 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2062 file, linenum, *err, args[1]);
2063 err_code |= ERR_ALERT | ERR_FATAL;
2064 goto out;
2065 }
2066
2067 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
2068 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2069 err_code |= ERR_ALERT | ERR_ABORT;
2070 goto out;
2071 }
2072
2073 /* the peers are linked backwards first */
2074 curpeers->count++;
2075 newpeer->next = curpeers->remote;
2076 curpeers->remote = newpeer;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002077 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002078 newpeer->conf.line = linenum;
2079
2080 newpeer->last_change = now.tv_sec;
2081 newpeer->id = strdup(args[1]);
2082
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002083 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002084 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01002085 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002086 err_code |= ERR_ALERT | ERR_FATAL;
2087 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002088 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01002089
2090 proto = protocol_by_family(sk->ss_family);
2091 if (!proto || !proto->connect) {
2092 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2093 file, linenum, args[0], args[1]);
2094 err_code |= ERR_ALERT | ERR_FATAL;
2095 goto out;
2096 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002097
2098 if (port1 != port2) {
2099 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2100 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002101 err_code |= ERR_ALERT | ERR_FATAL;
2102 goto out;
2103 }
2104
Willy Tarreau2aa38802013-02-20 19:20:59 +01002105 if (!port1) {
2106 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2107 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002108 err_code |= ERR_ALERT | ERR_FATAL;
2109 goto out;
2110 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002111
Emeric Brun32da3c42010-09-23 18:39:19 +02002112 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002113 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002114 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02002115 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02002116
Emeric Brun32da3c42010-09-23 18:39:19 +02002117 if (strcmp(newpeer->id, localpeer) == 0) {
2118 /* Current is local peer, it define a frontend */
2119 newpeer->local = 1;
Emeric Brunb3971ab2015-05-12 18:49:09 +02002120 peers->local = newpeer;
Emeric Brun32da3c42010-09-23 18:39:19 +02002121
2122 if (!curpeers->peers_fe) {
2123 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
2124 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2125 err_code |= ERR_ALERT | ERR_ABORT;
2126 goto out;
2127 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002128
Willy Tarreau237250c2011-07-29 01:49:03 +02002129 init_new_proxy(curpeers->peers_fe);
2130 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02002131 curpeers->peers_fe->id = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002132 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
2133 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau91d96282015-03-13 15:47:26 +01002134 peers_setup_frontend(curpeers->peers_fe);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002135
2136 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
2137
Willy Tarreau902636f2013-03-10 19:44:48 +01002138 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
2139 if (errmsg && *errmsg) {
2140 indent_msg(&errmsg, 2);
2141 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002142 }
2143 else
2144 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
2145 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002146 err_code |= ERR_FATAL;
2147 goto out;
2148 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02002149
2150 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01002151 l->maxaccept = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002152 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
2153 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
Willy Tarreau9903f0e2015-04-04 18:50:31 +02002154 l->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02002155 l->handler = process_stream;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002156 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01002157 l->default_target = ((struct proxy *)curpeers->peers_fe)->default_target;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002158 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
2159 global.maxsock += l->maxconn;
2160 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002161 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01002162 else {
2163 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
2164 file, linenum, args[0], args[1],
2165 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
2166 err_code |= ERR_FATAL;
2167 goto out;
2168 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002169 }
2170 } /* neither "peer" nor "peers" */
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002171 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
2172 curpeers->state = PR_STSTOPPED;
2173 }
2174 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
2175 curpeers->state = PR_STNEW;
2176 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002177 else if (*args[0] != 0) {
2178 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2179 err_code |= ERR_ALERT | ERR_FATAL;
2180 goto out;
2181 }
2182
2183out:
Willy Tarreau902636f2013-03-10 19:44:48 +01002184 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02002185 return err_code;
2186}
2187
Baptiste Assmann325137d2015-04-13 23:40:55 +02002188/*
2189 * Parse a <resolvers> section.
2190 * Returns the error code, 0 if OK, or any combination of :
2191 * - ERR_ABORT: must abort ASAP
2192 * - ERR_FATAL: we can continue parsing but not start the service
2193 * - ERR_WARN: a warning has been emitted
2194 * - ERR_ALERT: an alert has been emitted
2195 * Only the two first ones can stop processing, the two others are just
2196 * indicators.
2197 */
2198int cfg_parse_resolvers(const char *file, int linenum, char **args, int kwm)
2199{
2200 static struct dns_resolvers *curr_resolvers = NULL;
2201 struct dns_nameserver *newnameserver = NULL;
2202 const char *err;
2203 int err_code = 0;
2204 char *errmsg = NULL;
2205
2206 if (strcmp(args[0], "resolvers") == 0) { /* new resolvers section */
2207 if (!*args[1]) {
2208 Alert("parsing [%s:%d] : missing name for resolvers section.\n", file, linenum);
2209 err_code |= ERR_ALERT | ERR_ABORT;
2210 goto out;
2211 }
2212
2213 err = invalid_char(args[1]);
2214 if (err) {
2215 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2216 file, linenum, *err, args[0], args[1]);
2217 err_code |= ERR_ALERT | ERR_ABORT;
2218 goto out;
2219 }
2220
2221 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
2222 /* Error if two resolvers owns the same name */
2223 if (strcmp(curr_resolvers->id, args[1]) == 0) {
2224 Alert("Parsing [%s:%d]: resolvers '%s' has same name as another resolvers (declared at %s:%d).\n",
2225 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2226 err_code |= ERR_ALERT | ERR_ABORT;
2227 }
2228 }
2229
2230 if ((curr_resolvers = (struct dns_resolvers *)calloc(1, sizeof(struct dns_resolvers))) == NULL) {
2231 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2232 err_code |= ERR_ALERT | ERR_ABORT;
2233 goto out;
2234 }
2235
2236 /* default values */
2237 LIST_ADDQ(&dns_resolvers, &curr_resolvers->list);
2238 curr_resolvers->conf.file = strdup(file);
2239 curr_resolvers->conf.line = linenum;
2240 curr_resolvers->id = strdup(args[1]);
2241 curr_resolvers->query_ids = EB_ROOT;
2242 /* default hold period for valid is 10s */
Baptiste Assmann4c5490a2015-07-14 21:42:49 +02002243 curr_resolvers->hold.valid = 10000;
2244 curr_resolvers->timeout.retry = 1000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002245 curr_resolvers->resolve_retries = 3;
2246 LIST_INIT(&curr_resolvers->nameserver_list);
2247 LIST_INIT(&curr_resolvers->curr_resolution);
2248 }
2249 else if (strcmp(args[0], "nameserver") == 0) { /* nameserver definition */
2250 struct sockaddr_storage *sk;
2251 int port1, port2;
2252 struct protocol *proto;
2253
2254 if (!*args[2]) {
2255 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2256 file, linenum, args[0]);
2257 err_code |= ERR_ALERT | ERR_FATAL;
2258 goto out;
2259 }
2260
2261 err = invalid_char(args[1]);
2262 if (err) {
2263 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2264 file, linenum, *err, args[1]);
2265 err_code |= ERR_ALERT | ERR_FATAL;
2266 goto out;
2267 }
2268
2269 if ((newnameserver = (struct dns_nameserver *)calloc(1, sizeof(struct dns_nameserver))) == NULL) {
2270 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2271 err_code |= ERR_ALERT | ERR_ABORT;
2272 goto out;
2273 }
2274
2275 /* the nameservers are linked backward first */
2276 LIST_ADDQ(&curr_resolvers->nameserver_list, &newnameserver->list);
2277 curr_resolvers->count_nameservers++;
2278 newnameserver->resolvers = curr_resolvers;
2279 newnameserver->conf.file = strdup(file);
2280 newnameserver->conf.line = linenum;
2281 newnameserver->id = strdup(args[1]);
2282
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002283 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002284 if (!sk) {
2285 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2286 err_code |= ERR_ALERT | ERR_FATAL;
2287 goto out;
2288 }
2289
2290 proto = protocol_by_family(sk->ss_family);
2291 if (!proto || !proto->connect) {
2292 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2293 file, linenum, args[0], args[1]);
2294 err_code |= ERR_ALERT | ERR_FATAL;
2295 goto out;
2296 }
2297
2298 if (port1 != port2) {
2299 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2300 file, linenum, args[0], args[1], args[2]);
2301 err_code |= ERR_ALERT | ERR_FATAL;
2302 goto out;
2303 }
2304
2305 newnameserver->addr = *sk;
2306 }
2307 else if (strcmp(args[0], "hold") == 0) { /* hold periods */
2308 const char *res;
2309 unsigned int time;
2310
2311 if (!*args[2]) {
2312 Alert("parsing [%s:%d] : '%s' expects an <event> and a <time> as arguments.\n",
2313 file, linenum, args[0]);
2314 Alert("<event> can be either 'valid', 'nx', 'refused', 'timeout', or 'other'\n");
2315 err_code |= ERR_ALERT | ERR_FATAL;
2316 goto out;
2317 }
2318 res = parse_time_err(args[2], &time, TIME_UNIT_MS);
2319 if (res) {
2320 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2321 file, linenum, *res, args[0]);
2322 err_code |= ERR_ALERT | ERR_FATAL;
2323 goto out;
2324 }
2325 if (strcmp(args[1], "valid") == 0)
2326 curr_resolvers->hold.valid = time;
2327 else {
2328 Alert("parsing [%s:%d] : '%s' unknown <event>: '%s', expects 'valid'\n",
2329 file, linenum, args[0], args[1]);
2330 err_code |= ERR_ALERT | ERR_FATAL;
2331 goto out;
2332 }
2333
2334 }
2335 else if (strcmp(args[0], "resolve_retries") == 0) {
2336 if (!*args[1]) {
2337 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2338 file, linenum, args[0]);
2339 err_code |= ERR_ALERT | ERR_FATAL;
2340 goto out;
2341 }
2342 curr_resolvers->resolve_retries = atoi(args[1]);
2343 }
2344 else if (strcmp(args[0], "timeout") == 0) {
2345 const char *res;
2346 unsigned int timeout_retry;
2347
2348 if (!*args[2]) {
2349 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments.\n",
2350 file, linenum, args[0]);
2351 err_code |= ERR_ALERT | ERR_FATAL;
2352 goto out;
2353 }
2354 res = parse_time_err(args[2], &timeout_retry, TIME_UNIT_MS);
2355 if (res) {
2356 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2357 file, linenum, *res, args[0]);
2358 err_code |= ERR_ALERT | ERR_FATAL;
2359 goto out;
2360 }
2361 curr_resolvers->timeout.retry = timeout_retry;
2362 } /* neither "nameserver" nor "resolvers" */
2363 else if (*args[0] != 0) {
2364 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2365 err_code |= ERR_ALERT | ERR_FATAL;
2366 goto out;
2367 }
2368
2369 out:
2370 free(errmsg);
2371 return err_code;
2372}
Simon Horman0d16a402015-01-30 11:22:58 +09002373
2374/*
William Lallemand51097192015-04-14 16:35:22 +02002375 * Parse a line in a <listen>, <frontend> or <backend> section.
Simon Horman0d16a402015-01-30 11:22:58 +09002376 * Returns the error code, 0 if OK, or any combination of :
2377 * - ERR_ABORT: must abort ASAP
2378 * - ERR_FATAL: we can continue parsing but not start the service
2379 * - ERR_WARN: a warning has been emitted
2380 * - ERR_ALERT: an alert has been emitted
2381 * Only the two first ones can stop processing, the two others are just
2382 * indicators.
2383 */
2384int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
2385{
2386 static struct mailers *curmailers = NULL;
2387 struct mailer *newmailer = NULL;
2388 const char *err;
2389 int err_code = 0;
2390 char *errmsg = NULL;
2391
2392 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
2393 if (!*args[1]) {
2394 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
2395 err_code |= ERR_ALERT | ERR_ABORT;
2396 goto out;
2397 }
2398
2399 err = invalid_char(args[1]);
2400 if (err) {
2401 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2402 file, linenum, *err, args[0], args[1]);
2403 err_code |= ERR_ALERT | ERR_ABORT;
2404 goto out;
2405 }
2406
2407 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
2408 /*
2409 * If there are two proxies with the same name only following
2410 * combinations are allowed:
2411 */
2412 if (strcmp(curmailers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002413 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 +09002414 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002415 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman0d16a402015-01-30 11:22:58 +09002416 }
2417 }
2418
2419 if ((curmailers = (struct mailers *)calloc(1, sizeof(struct mailers))) == NULL) {
2420 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2421 err_code |= ERR_ALERT | ERR_ABORT;
2422 goto out;
2423 }
2424
2425 curmailers->next = mailers;
2426 mailers = curmailers;
2427 curmailers->conf.file = strdup(file);
2428 curmailers->conf.line = linenum;
2429 curmailers->id = strdup(args[1]);
2430 }
2431 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
2432 struct sockaddr_storage *sk;
2433 int port1, port2;
2434 struct protocol *proto;
2435
2436 if (!*args[2]) {
2437 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2438 file, linenum, args[0]);
2439 err_code |= ERR_ALERT | ERR_FATAL;
2440 goto out;
2441 }
2442
2443 err = invalid_char(args[1]);
2444 if (err) {
2445 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2446 file, linenum, *err, args[1]);
2447 err_code |= ERR_ALERT | ERR_FATAL;
2448 goto out;
2449 }
2450
2451 if ((newmailer = (struct mailer *)calloc(1, sizeof(struct mailer))) == NULL) {
2452 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2453 err_code |= ERR_ALERT | ERR_ABORT;
2454 goto out;
2455 }
2456
2457 /* the mailers are linked backwards first */
2458 curmailers->count++;
2459 newmailer->next = curmailers->mailer_list;
2460 curmailers->mailer_list = newmailer;
2461 newmailer->mailers = curmailers;
2462 newmailer->conf.file = strdup(file);
2463 newmailer->conf.line = linenum;
2464
2465 newmailer->id = strdup(args[1]);
2466
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002467 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Simon Horman0d16a402015-01-30 11:22:58 +09002468 if (!sk) {
2469 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2470 err_code |= ERR_ALERT | ERR_FATAL;
2471 goto out;
2472 }
2473
2474 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002475 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2476 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002477 file, linenum, args[0], args[1]);
2478 err_code |= ERR_ALERT | ERR_FATAL;
2479 goto out;
2480 }
2481
2482 if (port1 != port2) {
2483 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2484 file, linenum, args[0], args[1], args[2]);
2485 err_code |= ERR_ALERT | ERR_FATAL;
2486 goto out;
2487 }
2488
2489 if (!port1) {
2490 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2491 file, linenum, args[0], args[1], args[2]);
2492 err_code |= ERR_ALERT | ERR_FATAL;
2493 goto out;
2494 }
2495
2496 newmailer->addr = *sk;
2497 newmailer->proto = proto;
2498 newmailer->xprt = &raw_sock;
2499 newmailer->sock_init_arg = NULL;
2500 } /* neither "mailer" nor "mailers" */
2501 else if (*args[0] != 0) {
2502 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2503 err_code |= ERR_ALERT | ERR_FATAL;
2504 goto out;
2505 }
2506
2507out:
2508 free(errmsg);
2509 return err_code;
2510}
2511
Simon Horman9dc49962015-01-30 11:22:59 +09002512static void free_email_alert(struct proxy *p)
2513{
2514 free(p->email_alert.mailers.name);
2515 p->email_alert.mailers.name = NULL;
2516 free(p->email_alert.from);
2517 p->email_alert.from = NULL;
2518 free(p->email_alert.to);
2519 p->email_alert.to = NULL;
2520 free(p->email_alert.myhostname);
2521 p->email_alert.myhostname = NULL;
2522}
2523
Willy Tarreau3842f002009-06-14 11:39:52 +02002524int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002525{
2526 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002527 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002528 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002529 int rc;
2530 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002531 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002532 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002533 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002534 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002535 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002536
Willy Tarreau977b8e42006-12-29 14:19:17 +01002537 if (!strcmp(args[0], "listen"))
2538 rc = PR_CAP_LISTEN;
2539 else if (!strcmp(args[0], "frontend"))
2540 rc = PR_CAP_FE | PR_CAP_RS;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02002541 else if (!strcmp(args[0], "backend"))
Willy Tarreau977b8e42006-12-29 14:19:17 +01002542 rc = PR_CAP_BE | PR_CAP_RS;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002543 else
2544 rc = PR_CAP_NONE;
2545
2546 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002547 if (!*args[1]) {
2548 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
2549 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
2550 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002551 err_code |= ERR_ALERT | ERR_ABORT;
2552 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002553 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002554
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002555 err = invalid_char(args[1]);
2556 if (err) {
2557 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2558 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002559 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002560 }
2561
Willy Tarreau8f50b682015-05-26 11:45:02 +02002562 curproxy = (rc & PR_CAP_FE) ? proxy_fe_by_name(args[1]) : proxy_be_by_name(args[1]);
2563 if (curproxy) {
2564 Alert("Parsing [%s:%d]: %s '%s' has the same name as %s '%s' declared at %s:%d.\n",
2565 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2566 curproxy->id, curproxy->conf.file, curproxy->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002567 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002568 }
2569
Willy Tarreaubaaee002006-06-26 02:48:02 +02002570 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
2571 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002572 err_code |= ERR_ALERT | ERR_ABORT;
2573 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002574 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002575
Willy Tarreau97cb7802010-01-03 20:23:58 +01002576 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002577 curproxy->next = proxy;
2578 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002579 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2580 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002581 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002582 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002583 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002584 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002585
William Lallemand6e62fb62015-04-28 16:55:23 +02002586 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2587 if (curproxy->cap & PR_CAP_FE)
2588 Alert("parsing [%s:%d] : please use the 'bind' keyword for listening addresses.\n", file, linenum);
2589 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002590 }
2591
2592 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002593 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002594 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002595
Willy Tarreaubaaee002006-06-26 02:48:02 +02002596 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002597 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002598 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002599 curproxy->no_options = defproxy.no_options;
2600 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002601 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002602 curproxy->except_net = defproxy.except_net;
2603 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002604 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002605 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002606
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002607 if (defproxy.fwdfor_hdr_len) {
2608 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2609 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2610 }
2611
Willy Tarreaub86db342009-11-30 11:50:16 +01002612 if (defproxy.orgto_hdr_len) {
2613 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2614 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2615 }
2616
Mark Lamourinec2247f02012-01-04 13:02:01 -05002617 if (defproxy.server_id_hdr_len) {
2618 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2619 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2620 }
2621
Willy Tarreau977b8e42006-12-29 14:19:17 +01002622 if (curproxy->cap & PR_CAP_FE) {
2623 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002624 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002625 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002626
2627 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002628 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2629 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002630
2631 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2632 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002633
Willy Tarreau977b8e42006-12-29 14:19:17 +01002634 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002635 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002636 curproxy->fullconn = defproxy.fullconn;
2637 curproxy->conn_retries = defproxy.conn_retries;
Joseph Lynch726ab712015-05-11 23:25:34 -07002638 curproxy->redispatch_after = defproxy.redispatch_after;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002639 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002640
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002641 if (defproxy.check_req) {
2642 curproxy->check_req = calloc(1, defproxy.check_len);
2643 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2644 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002645 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002646
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002647 if (defproxy.expect_str) {
2648 curproxy->expect_str = strdup(defproxy.expect_str);
2649 if (defproxy.expect_regex) {
2650 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002651 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2652 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002653 }
2654 }
2655
Willy Tarreau67402132012-05-31 20:40:20 +02002656 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002657 if (defproxy.cookie_name)
2658 curproxy->cookie_name = strdup(defproxy.cookie_name);
2659 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002660 if (defproxy.cookie_domain)
2661 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002662
Willy Tarreau31936852010-10-06 16:59:56 +02002663 if (defproxy.cookie_maxidle)
2664 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2665
2666 if (defproxy.cookie_maxlife)
2667 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2668
Emeric Brun647caf12009-06-30 17:57:00 +02002669 if (defproxy.rdp_cookie_name)
2670 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2671 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2672
Willy Tarreau01732802007-11-01 22:48:15 +01002673 if (defproxy.url_param_name)
2674 curproxy->url_param_name = strdup(defproxy.url_param_name);
2675 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002676
Benoitaffb4812009-03-25 13:02:10 +01002677 if (defproxy.hh_name)
2678 curproxy->hh_name = strdup(defproxy.hh_name);
2679 curproxy->hh_len = defproxy.hh_len;
2680 curproxy->hh_match_domain = defproxy.hh_match_domain;
2681
Willy Tarreauef9a3602012-12-08 22:29:20 +01002682 if (defproxy.conn_src.iface_name)
2683 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2684 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002685 curproxy->conn_src.opts = defproxy.conn_src.opts;
Willy Tarreau29fbe512015-08-20 19:35:14 +02002686#if defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002687 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002688#endif
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02002689 curproxy->load_server_state_from_file = defproxy.load_server_state_from_file;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002690 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002691
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002692 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002693 if (defproxy.capture_name)
2694 curproxy->capture_name = strdup(defproxy.capture_name);
2695 curproxy->capture_namelen = defproxy.capture_namelen;
2696 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002697 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002698
Willy Tarreau977b8e42006-12-29 14:19:17 +01002699 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002700 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002701 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002702 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002703 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002704 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002705 curproxy->mon_net = defproxy.mon_net;
2706 curproxy->mon_mask = defproxy.mon_mask;
2707 if (defproxy.monitor_uri)
2708 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2709 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002710 if (defproxy.defbe.name)
2711 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002712
2713 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002714 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2715 if (curproxy->conf.logformat_string &&
2716 curproxy->conf.logformat_string != default_http_log_format &&
2717 curproxy->conf.logformat_string != default_tcp_log_format &&
2718 curproxy->conf.logformat_string != clf_http_log_format)
2719 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2720
2721 if (defproxy.conf.lfs_file) {
2722 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2723 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2724 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002725 }
2726
2727 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002728 curproxy->timeout.connect = defproxy.timeout.connect;
2729 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002730 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002731 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002732 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002733 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002734 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002735 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002736 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002737 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002738 }
2739
Willy Tarreaubaaee002006-06-26 02:48:02 +02002740 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002741 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002742
2743 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002744 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002745 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002746 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002747 LIST_INIT(&node->list);
2748 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2749 }
2750
Willy Tarreau62a61232013-04-12 18:13:46 +02002751 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2752 if (curproxy->conf.uniqueid_format_string)
2753 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2754
Willy Tarreau094af4e2015-01-07 15:03:42 +01002755 if (defproxy.log_tag)
2756 curproxy->log_tag = strdup(defproxy.log_tag);
2757
Willy Tarreau62a61232013-04-12 18:13:46 +02002758 if (defproxy.conf.uif_file) {
2759 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2760 curproxy->conf.uif_line = defproxy.conf.uif_line;
2761 }
William Lallemanda73203e2012-03-12 12:48:57 +01002762
2763 /* copy default header unique id */
2764 if (defproxy.header_unique_id)
2765 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2766
William Lallemand82fe75c2012-10-23 10:25:10 +02002767 /* default compression options */
2768 if (defproxy.comp != NULL) {
2769 curproxy->comp = calloc(1, sizeof(struct comp));
2770 curproxy->comp->algos = defproxy.comp->algos;
2771 curproxy->comp->types = defproxy.comp->types;
2772 }
2773
Willy Tarreaubaaee002006-06-26 02:48:02 +02002774 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002775 curproxy->conf.used_listener_id = EB_ROOT;
2776 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002777
Simon Horman98637e52014-06-20 12:30:16 +09002778 if (defproxy.check_path)
2779 curproxy->check_path = strdup(defproxy.check_path);
2780 if (defproxy.check_command)
2781 curproxy->check_command = strdup(defproxy.check_command);
2782
Simon Horman9dc49962015-01-30 11:22:59 +09002783 if (defproxy.email_alert.mailers.name)
2784 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2785 if (defproxy.email_alert.from)
2786 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2787 if (defproxy.email_alert.to)
2788 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2789 if (defproxy.email_alert.myhostname)
2790 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09002791 curproxy->email_alert.level = defproxy.email_alert.level;
Simon Horman9dc49962015-01-30 11:22:59 +09002792
Willy Tarreau93893792009-07-23 13:19:11 +02002793 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002794 }
2795 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2796 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002797 /* FIXME-20070101: we should do this too at the end of the
2798 * config parsing to free all default values.
2799 */
William Lallemand6e62fb62015-04-28 16:55:23 +02002800 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2801 err_code |= ERR_ABORT;
2802 goto out;
2803 }
2804
Willy Tarreaua534fea2008-08-03 12:19:50 +02002805 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002806 free(defproxy.check_command);
2807 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002808 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002809 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002810 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002811 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002812 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002813 free(defproxy.capture_name);
2814 free(defproxy.monitor_uri);
2815 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002816 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002817 free(defproxy.fwdfor_hdr_name);
2818 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002819 free(defproxy.orgto_hdr_name);
2820 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002821 free(defproxy.server_id_hdr_name);
2822 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002823 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002824 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002825 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002826 free(defproxy.expect_regex);
2827 defproxy.expect_regex = NULL;
2828 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002829
Willy Tarreau62a61232013-04-12 18:13:46 +02002830 if (defproxy.conf.logformat_string != default_http_log_format &&
2831 defproxy.conf.logformat_string != default_tcp_log_format &&
2832 defproxy.conf.logformat_string != clf_http_log_format)
2833 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002834
Willy Tarreau62a61232013-04-12 18:13:46 +02002835 free(defproxy.conf.uniqueid_format_string);
2836 free(defproxy.conf.lfs_file);
2837 free(defproxy.conf.uif_file);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002838 free(defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09002839 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02002840
Willy Tarreaua534fea2008-08-03 12:19:50 +02002841 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002842 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002843
Willy Tarreaubaaee002006-06-26 02:48:02 +02002844 /* we cannot free uri_auth because it might already be used */
2845 init_default_instance();
2846 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002847 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2848 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002849 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002850 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002851 }
2852 else if (curproxy == NULL) {
2853 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002854 err_code |= ERR_ALERT | ERR_FATAL;
2855 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002856 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002857
2858 /* update the current file and line being parsed */
2859 curproxy->conf.args.file = curproxy->conf.file;
2860 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002861
2862 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002863 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2864 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2865 if (err_code & ERR_FATAL)
2866 goto out;
2867 }
2868 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002869 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002870 int cur_arg;
2871
Willy Tarreaubaaee002006-06-26 02:48:02 +02002872 if (curproxy == &defproxy) {
2873 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002874 err_code |= ERR_ALERT | ERR_FATAL;
2875 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002876 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002877 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002878 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002879
Willy Tarreau24709282013-03-10 21:32:12 +01002880 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002881 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002882 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002883 err_code |= ERR_ALERT | ERR_FATAL;
2884 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002885 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002886
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002887 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002888
2889 /* use default settings for unix sockets */
2890 bind_conf->ux.uid = global.unix_bind.ux.uid;
2891 bind_conf->ux.gid = global.unix_bind.ux.gid;
2892 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002893
2894 /* NOTE: the following line might create several listeners if there
2895 * are comma-separated IPs or port ranges. So all further processing
2896 * will have to be applied to all listeners created after last_listen.
2897 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002898 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2899 if (errmsg && *errmsg) {
2900 indent_msg(&errmsg, 2);
2901 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002902 }
2903 else
2904 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2905 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002906 err_code |= ERR_ALERT | ERR_FATAL;
2907 goto out;
2908 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002909
Willy Tarreau4348fad2012-09-20 16:48:07 +02002910 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2911 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002912 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002913 }
2914
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002915 cur_arg = 2;
2916 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002917 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002918 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002919 char *err;
2920
Willy Tarreau26982662012-09-12 23:17:10 +02002921 kw = bind_find_kw(args[cur_arg]);
2922 if (kw) {
2923 char *err = NULL;
2924 int code;
2925
2926 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002927 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2928 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002929 cur_arg += 1 + kw->skip ;
2930 err_code |= ERR_ALERT | ERR_FATAL;
2931 goto out;
2932 }
2933
Willy Tarreau4348fad2012-09-20 16:48:07 +02002934 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002935 err_code |= code;
2936
2937 if (code) {
2938 if (err && *err) {
2939 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002940 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002941 }
2942 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002943 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2944 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002945 if (code & ERR_FATAL) {
2946 free(err);
2947 cur_arg += 1 + kw->skip;
2948 goto out;
2949 }
2950 }
2951 free(err);
2952 cur_arg += 1 + kw->skip;
2953 continue;
2954 }
2955
Willy Tarreau8638f482012-09-18 18:01:17 +02002956 err = NULL;
2957 if (!bind_dumped) {
2958 bind_dump_kws(&err);
2959 indent_msg(&err, 4);
2960 bind_dumped = 1;
2961 }
2962
2963 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2964 file, linenum, args[0], args[1], args[cur_arg],
2965 err ? " Registered keywords :" : "", err ? err : "");
2966 free(err);
2967
Willy Tarreau93893792009-07-23 13:19:11 +02002968 err_code |= ERR_ALERT | ERR_FATAL;
2969 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002970 }
Willy Tarreau93893792009-07-23 13:19:11 +02002971 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002972 }
2973 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002974 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002975 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2976 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002977 err_code |= ERR_ALERT | ERR_FATAL;
2978 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002979 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002980 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002981 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002982
Willy Tarreaubaaee002006-06-26 02:48:02 +02002983 /* flush useless bits */
2984 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002985 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002986 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002987 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002988 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002989 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002990
William Lallemanddf1425a2015-04-28 20:17:49 +02002991 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2992 goto out;
2993
Willy Tarreau1c47f852006-07-09 08:22:27 +02002994 if (!*args[1]) {
2995 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2996 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002997 err_code |= ERR_ALERT | ERR_FATAL;
2998 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002999 }
3000
Willy Tarreaua534fea2008-08-03 12:19:50 +02003001 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003002 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02003003 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003004 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02003005 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
3006
Willy Tarreau93893792009-07-23 13:19:11 +02003007 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003008 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003009 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
William Lallemanddf1425a2015-04-28 20:17:49 +02003010 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3011 goto out;
3012
Willy Tarreaubaaee002006-06-26 02:48:02 +02003013 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
3014 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
3015 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
3016 else {
3017 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003018 err_code |= ERR_ALERT | ERR_FATAL;
3019 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003020 }
3021 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003022 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003023 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003024
3025 if (curproxy == &defproxy) {
3026 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3027 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003028 err_code |= ERR_ALERT | ERR_FATAL;
3029 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003030 }
3031
William Lallemanddf1425a2015-04-28 20:17:49 +02003032 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3033 goto out;
3034
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003035 if (!*args[1]) {
3036 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3037 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003038 err_code |= ERR_ALERT | ERR_FATAL;
3039 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003040 }
3041
3042 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003043 curproxy->conf.id.key = curproxy->uuid;
Willy Tarreau0d1fdf72015-05-27 16:44:02 +02003044 curproxy->options |= PR_O_FORCED_ID;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003045
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003046 if (curproxy->uuid <= 0) {
3047 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003048 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003049 err_code |= ERR_ALERT | ERR_FATAL;
3050 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003051 }
3052
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003053 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
3054 if (node) {
3055 struct proxy *target = container_of(node, struct proxy, conf.id);
3056 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
3057 file, linenum, proxy_type_str(curproxy), curproxy->id,
3058 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
3059 err_code |= ERR_ALERT | ERR_FATAL;
3060 goto out;
3061 }
3062 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003063 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003064 else if (!strcmp(args[0], "description")) {
3065 int i, len=0;
3066 char *d;
3067
Cyril Bonté99ed3272010-01-24 23:29:44 +01003068 if (curproxy == &defproxy) {
3069 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3070 file, linenum, args[0]);
3071 err_code |= ERR_ALERT | ERR_FATAL;
3072 goto out;
3073 }
3074
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003075 if (!*args[1]) {
3076 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
3077 file, linenum, args[0]);
3078 return -1;
3079 }
3080
Willy Tarreau348acfe2014-04-14 15:00:39 +02003081 for (i = 1; *args[i]; i++)
3082 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003083
3084 d = (char *)calloc(1, len);
3085 curproxy->desc = d;
3086
Willy Tarreau348acfe2014-04-14 15:00:39 +02003087 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
3088 for (i = 2; *args[i]; i++)
3089 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003090
3091 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003092 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
William Lallemanddf1425a2015-04-28 20:17:49 +02003093 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3094 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003095 curproxy->state = PR_STSTOPPED;
3096 }
3097 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
William Lallemanddf1425a2015-04-28 20:17:49 +02003098 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3099 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003100 curproxy->state = PR_STNEW;
3101 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003102 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
3103 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003104 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003105
3106 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003107 unsigned int low, high;
3108
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003109 if (strcmp(args[cur_arg], "all") == 0) {
3110 set = 0;
3111 break;
3112 }
3113 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003114 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003115 }
3116 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003117 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003118 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01003119 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003120 char *dash = strchr(args[cur_arg], '-');
3121
3122 low = high = str2uic(args[cur_arg]);
3123 if (dash)
3124 high = str2uic(dash + 1);
3125
3126 if (high < low) {
3127 unsigned int swap = low;
3128 low = high;
3129 high = swap;
3130 }
3131
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003132 if (low < 1 || high > LONGBITS) {
3133 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
3134 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02003135 err_code |= ERR_ALERT | ERR_FATAL;
3136 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003137 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01003138 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003139 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003140 }
3141 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003142 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
3143 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003144 err_code |= ERR_ALERT | ERR_FATAL;
3145 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003146 }
3147 cur_arg++;
3148 }
3149 curproxy->bind_proc = set;
3150 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003151 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02003152 if (curproxy == &defproxy) {
3153 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003154 err_code |= ERR_ALERT | ERR_FATAL;
3155 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003156 }
3157
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003158 err = invalid_char(args[1]);
3159 if (err) {
3160 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
3161 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003162 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003163 }
3164
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01003165 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003166 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
3167 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003168 err_code |= ERR_ALERT | ERR_FATAL;
3169 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003170 }
3171 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003172 else if (!strcmp(args[0], "cookie")) { /* cookie name */
3173 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003174
Willy Tarreau977b8e42006-12-29 14:19:17 +01003175 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003176 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003177
Willy Tarreaubaaee002006-06-26 02:48:02 +02003178 if (*(args[1]) == 0) {
3179 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
3180 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003181 err_code |= ERR_ALERT | ERR_FATAL;
3182 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003183 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003184
Willy Tarreau67402132012-05-31 20:40:20 +02003185 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003186 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01003187 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003188 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003189 curproxy->cookie_name = strdup(args[1]);
3190 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003191
Willy Tarreaubaaee002006-06-26 02:48:02 +02003192 cur_arg = 2;
3193 while (*(args[cur_arg])) {
3194 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003195 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003196 }
3197 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003198 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003199 }
3200 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003201 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003202 }
3203 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003204 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003205 }
3206 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003207 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003208 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003209 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003210 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003211 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003212 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003213 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003214 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02003215 else if (!strcmp(args[cur_arg], "httponly")) {
3216 curproxy->ck_opts |= PR_CK_HTTPONLY;
3217 }
3218 else if (!strcmp(args[cur_arg], "secure")) {
3219 curproxy->ck_opts |= PR_CK_SECURE;
3220 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003221 else if (!strcmp(args[cur_arg], "domain")) {
3222 if (!*args[cur_arg + 1]) {
3223 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
3224 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003225 err_code |= ERR_ALERT | ERR_FATAL;
3226 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003227 }
3228
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003229 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003230 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003231 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
3232 " dots nor does not start with a dot."
3233 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003234 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003235 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003236 }
3237
3238 err = invalid_domainchar(args[cur_arg + 1]);
3239 if (err) {
3240 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
3241 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003242 err_code |= ERR_ALERT | ERR_FATAL;
3243 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003244 }
3245
Willy Tarreau68a897b2009-12-03 23:28:34 +01003246 if (!curproxy->cookie_domain) {
3247 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
3248 } else {
3249 /* one domain was already specified, add another one by
3250 * building the string which will be returned along with
3251 * the cookie.
3252 */
3253 char *new_ptr;
3254 int new_len = strlen(curproxy->cookie_domain) +
3255 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
3256 new_ptr = malloc(new_len);
3257 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
3258 free(curproxy->cookie_domain);
3259 curproxy->cookie_domain = new_ptr;
3260 }
Willy Tarreau31936852010-10-06 16:59:56 +02003261 cur_arg++;
3262 }
3263 else if (!strcmp(args[cur_arg], "maxidle")) {
3264 unsigned int maxidle;
3265 const char *res;
3266
3267 if (!*args[cur_arg + 1]) {
3268 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
3269 file, linenum, args[cur_arg]);
3270 err_code |= ERR_ALERT | ERR_FATAL;
3271 goto out;
3272 }
3273
3274 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
3275 if (res) {
3276 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3277 file, linenum, *res, args[cur_arg]);
3278 err_code |= ERR_ALERT | ERR_FATAL;
3279 goto out;
3280 }
3281 curproxy->cookie_maxidle = maxidle;
3282 cur_arg++;
3283 }
3284 else if (!strcmp(args[cur_arg], "maxlife")) {
3285 unsigned int maxlife;
3286 const char *res;
3287
3288 if (!*args[cur_arg + 1]) {
3289 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
3290 file, linenum, args[cur_arg]);
3291 err_code |= ERR_ALERT | ERR_FATAL;
3292 goto out;
3293 }
3294
3295 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
3296 if (res) {
3297 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3298 file, linenum, *res, args[cur_arg]);
3299 err_code |= ERR_ALERT | ERR_FATAL;
3300 goto out;
3301 }
3302 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003303 cur_arg++;
3304 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003305 else {
Willy Tarreau31936852010-10-06 16:59:56 +02003306 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 +02003307 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003308 err_code |= ERR_ALERT | ERR_FATAL;
3309 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003310 }
3311 cur_arg++;
3312 }
Willy Tarreau67402132012-05-31 20:40:20 +02003313 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003314 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
3315 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003316 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003317 }
3318
Willy Tarreau67402132012-05-31 20:40:20 +02003319 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003320 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
3321 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003322 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003323 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003324
Willy Tarreau67402132012-05-31 20:40:20 +02003325 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003326 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
3327 file, linenum);
3328 err_code |= ERR_ALERT | ERR_FATAL;
3329 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003330 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09003331 else if (!strcmp(args[0], "email-alert")) {
3332 if (*(args[1]) == 0) {
3333 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3334 file, linenum, args[0]);
3335 err_code |= ERR_ALERT | ERR_FATAL;
3336 goto out;
3337 }
3338
3339 if (!strcmp(args[1], "from")) {
3340 if (*(args[1]) == 0) {
3341 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3342 file, linenum, args[1]);
3343 err_code |= ERR_ALERT | ERR_FATAL;
3344 goto out;
3345 }
3346 free(curproxy->email_alert.from);
3347 curproxy->email_alert.from = strdup(args[2]);
3348 }
3349 else if (!strcmp(args[1], "mailers")) {
3350 if (*(args[1]) == 0) {
3351 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3352 file, linenum, args[1]);
3353 err_code |= ERR_ALERT | ERR_FATAL;
3354 goto out;
3355 }
3356 free(curproxy->email_alert.mailers.name);
3357 curproxy->email_alert.mailers.name = strdup(args[2]);
3358 }
3359 else if (!strcmp(args[1], "myhostname")) {
3360 if (*(args[1]) == 0) {
3361 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3362 file, linenum, args[1]);
3363 err_code |= ERR_ALERT | ERR_FATAL;
3364 goto out;
3365 }
3366 free(curproxy->email_alert.myhostname);
3367 curproxy->email_alert.myhostname = strdup(args[2]);
3368 }
Simon Horman64e34162015-02-06 11:11:57 +09003369 else if (!strcmp(args[1], "level")) {
3370 curproxy->email_alert.level = get_log_level(args[2]);
3371 if (curproxy->email_alert.level < 0) {
3372 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
3373 file, linenum, args[1], args[2]);
3374 err_code |= ERR_ALERT | ERR_FATAL;
3375 goto out;
3376 }
3377 }
Simon Horman9dc49962015-01-30 11:22:59 +09003378 else if (!strcmp(args[1], "to")) {
3379 if (*(args[1]) == 0) {
3380 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3381 file, linenum, args[1]);
3382 err_code |= ERR_ALERT | ERR_FATAL;
3383 goto out;
3384 }
3385 free(curproxy->email_alert.to);
3386 curproxy->email_alert.to = strdup(args[2]);
3387 }
3388 else {
3389 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
3390 file, linenum, args[1]);
3391 err_code |= ERR_ALERT | ERR_FATAL;
3392 goto out;
3393 }
Simon Horman64e34162015-02-06 11:11:57 +09003394 /* Indicate that the email_alert is at least partially configured */
3395 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09003396 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09003397 else if (!strcmp(args[0], "external-check")) {
3398 if (*(args[1]) == 0) {
3399 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3400 file, linenum, args[0]);
3401 err_code |= ERR_ALERT | ERR_FATAL;
3402 goto out;
3403 }
3404
3405 if (!strcmp(args[1], "command")) {
William Lallemanddf1425a2015-04-28 20:17:49 +02003406 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3407 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09003408 if (*(args[1]) == 0) {
3409 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3410 file, linenum, args[1]);
3411 err_code |= ERR_ALERT | ERR_FATAL;
3412 goto out;
3413 }
3414 free(curproxy->check_command);
3415 curproxy->check_command = strdup(args[2]);
3416 }
3417 else if (!strcmp(args[1], "path")) {
William Lallemanddf1425a2015-04-28 20:17:49 +02003418 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3419 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09003420 if (*(args[1]) == 0) {
3421 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3422 file, linenum, args[1]);
3423 err_code |= ERR_ALERT | ERR_FATAL;
3424 goto out;
3425 }
3426 free(curproxy->check_path);
3427 curproxy->check_path = strdup(args[2]);
3428 }
3429 else {
3430 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
3431 file, linenum, args[1]);
3432 err_code |= ERR_ALERT | ERR_FATAL;
3433 goto out;
3434 }
3435 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02003436 else if (!strcmp(args[0], "persist")) { /* persist */
3437 if (*(args[1]) == 0) {
3438 Alert("parsing [%s:%d] : missing persist method.\n",
3439 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003440 err_code |= ERR_ALERT | ERR_FATAL;
3441 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003442 }
3443
3444 if (!strncmp(args[1], "rdp-cookie", 10)) {
3445 curproxy->options2 |= PR_O2_RDPC_PRST;
3446
Emeric Brunb982a3d2010-01-04 15:45:53 +01003447 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003448 const char *beg, *end;
3449
3450 beg = args[1] + 11;
3451 end = strchr(beg, ')');
3452
William Lallemanddf1425a2015-04-28 20:17:49 +02003453 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3454 goto out;
3455
Emeric Brun647caf12009-06-30 17:57:00 +02003456 if (!end || end == beg) {
3457 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3458 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003459 err_code |= ERR_ALERT | ERR_FATAL;
3460 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003461 }
3462
3463 free(curproxy->rdp_cookie_name);
3464 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3465 curproxy->rdp_cookie_len = end-beg;
3466 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003467 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003468 free(curproxy->rdp_cookie_name);
3469 curproxy->rdp_cookie_name = strdup("msts");
3470 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3471 }
3472 else { /* syntax */
3473 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3474 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003475 err_code |= ERR_ALERT | ERR_FATAL;
3476 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003477 }
3478 }
3479 else {
3480 Alert("parsing [%s:%d] : unknown persist method.\n",
3481 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003482 err_code |= ERR_ALERT | ERR_FATAL;
3483 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003484 }
3485 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003486 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreau6db62c52015-08-10 19:04:29 +02003487 Alert("parsing [%s:%d] : '%s' is not supported anymore, please check the documentation.\n", file, linenum, args[0]);
3488 err_code |= ERR_ALERT | ERR_FATAL;
3489 goto out;
3490 }
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02003491 else if (!strcmp(args[0], "load-server-state-from-file")) {
3492 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3493 err_code |= ERR_WARN;
3494 if (!strcmp(args[1], "global")) { /* use the file pointed to by global server-state-file directive */
3495 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_GLOBAL;
3496 }
3497 else if (!strcmp(args[1], "local")) { /* use the server-state-file-name variable to locate the server-state file */
3498 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_LOCAL;
3499 }
3500 else if (!strcmp(args[1], "none")) { /* don't use server-state-file directive for this backend */
3501 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
3502 }
3503 else {
3504 Alert("parsing [%s:%d] : '%s' expects 'global', 'local' or 'none'. Got '%s'\n",
3505 file, linenum, args[0], args[1]);
3506 err_code |= ERR_ALERT | ERR_FATAL;
3507 goto out;
3508 }
3509 }
3510 else if (!strcmp(args[0], "server-state-file-name")) {
3511 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3512 err_code |= ERR_WARN;
3513 if (*(args[1]) == 0) {
3514 Alert("parsing [%s:%d] : '%s' expects 'use-backend-name' or a string. Got no argument\n",
3515 file, linenum, args[0]);
3516 err_code |= ERR_ALERT | ERR_FATAL;
3517 goto out;
3518 }
3519 else if (!strcmp(args[1], "use-backend-name"))
3520 curproxy->server_state_file_name = strdup(curproxy->id);
3521 else
3522 curproxy->server_state_file_name = strdup(args[1]);
3523 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003524 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003525 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003526 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003527
Willy Tarreaubaaee002006-06-26 02:48:02 +02003528 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003529 if (curproxy == &defproxy) {
3530 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3531 err_code |= ERR_ALERT | ERR_FATAL;
3532 goto out;
3533 }
3534
William Lallemand1a748ae2015-05-19 16:37:23 +02003535 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3536 goto out;
3537
Willy Tarreaubaaee002006-06-26 02:48:02 +02003538 if (*(args[4]) == 0) {
3539 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3540 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003541 err_code |= ERR_ALERT | ERR_FATAL;
3542 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003543 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003544 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003545 curproxy->capture_name = strdup(args[2]);
3546 curproxy->capture_namelen = strlen(curproxy->capture_name);
3547 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003548 curproxy->to_log |= LW_COOKIE;
3549 }
3550 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3551 struct cap_hdr *hdr;
3552
3553 if (curproxy == &defproxy) {
3554 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 +02003555 err_code |= ERR_ALERT | ERR_FATAL;
3556 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003557 }
3558
William Lallemand1a748ae2015-05-19 16:37:23 +02003559 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3560 goto out;
3561
Willy Tarreaubaaee002006-06-26 02:48:02 +02003562 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3563 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3564 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003565 err_code |= ERR_ALERT | ERR_FATAL;
3566 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003567 }
3568
3569 hdr = calloc(sizeof(struct cap_hdr), 1);
3570 hdr->next = curproxy->req_cap;
3571 hdr->name = strdup(args[3]);
3572 hdr->namelen = strlen(args[3]);
3573 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003574 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003575 hdr->index = curproxy->nb_req_cap++;
3576 curproxy->req_cap = hdr;
3577 curproxy->to_log |= LW_REQHDR;
3578 }
3579 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3580 struct cap_hdr *hdr;
3581
3582 if (curproxy == &defproxy) {
3583 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 +02003584 err_code |= ERR_ALERT | ERR_FATAL;
3585 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003586 }
3587
William Lallemand1a748ae2015-05-19 16:37:23 +02003588 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3589 goto out;
3590
Willy Tarreaubaaee002006-06-26 02:48:02 +02003591 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3592 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3593 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003594 err_code |= ERR_ALERT | ERR_FATAL;
3595 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003596 }
3597 hdr = calloc(sizeof(struct cap_hdr), 1);
3598 hdr->next = curproxy->rsp_cap;
3599 hdr->name = strdup(args[3]);
3600 hdr->namelen = strlen(args[3]);
3601 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003602 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003603 hdr->index = curproxy->nb_rsp_cap++;
3604 curproxy->rsp_cap = hdr;
3605 curproxy->to_log |= LW_RSPHDR;
3606 }
3607 else {
3608 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3609 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003610 err_code |= ERR_ALERT | ERR_FATAL;
3611 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003612 }
3613 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003614 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003615 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003616 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003617
William Lallemanddf1425a2015-04-28 20:17:49 +02003618 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3619 goto out;
3620
Willy Tarreaubaaee002006-06-26 02:48:02 +02003621 if (*(args[1]) == 0) {
3622 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3623 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003624 err_code |= ERR_ALERT | ERR_FATAL;
3625 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003626 }
3627 curproxy->conn_retries = atol(args[1]);
3628 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003629 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003630 struct act_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003631
3632 if (curproxy == &defproxy) {
3633 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3634 err_code |= ERR_ALERT | ERR_FATAL;
3635 goto out;
3636 }
3637
Willy Tarreau20b0de52012-12-24 15:45:22 +01003638 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003639 !LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003640 (LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3641 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_DENY ||
3642 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REDIR ||
3643 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REQ_AUTH)) {
Willy Tarreau20b0de52012-12-24 15:45:22 +01003644 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 +01003645 file, linenum, args[0]);
3646 err_code |= ERR_WARN;
3647 }
3648
Willy Tarreauff011f22011-01-06 17:51:27 +01003649 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003650
Willy Tarreauff011f22011-01-06 17:51:27 +01003651 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003652 err_code |= ERR_ALERT | ERR_ABORT;
3653 goto out;
3654 }
3655
Willy Tarreau5002f572014-04-23 01:32:02 +02003656 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003657 err_code |= warnif_cond_conflicts(rule->cond,
3658 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3659 file, linenum);
3660
Willy Tarreauff011f22011-01-06 17:51:27 +01003661 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003662 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003663 else if (!strcmp(args[0], "http-response")) { /* response access control */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003664 struct act_rule *rule;
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003665
3666 if (curproxy == &defproxy) {
3667 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3668 err_code |= ERR_ALERT | ERR_FATAL;
3669 goto out;
3670 }
3671
3672 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003673 !LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003674 (LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3675 LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_DENY)) {
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003676 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3677 file, linenum, args[0]);
3678 err_code |= ERR_WARN;
3679 }
3680
3681 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3682
3683 if (!rule) {
3684 err_code |= ERR_ALERT | ERR_ABORT;
3685 goto out;
3686 }
3687
3688 err_code |= warnif_cond_conflicts(rule->cond,
3689 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3690 file, linenum);
3691
3692 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3693 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003694 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3695 /* set the header name and length into the proxy structure */
3696 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3697 err_code |= ERR_WARN;
3698
3699 if (!*args[1]) {
3700 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3701 file, linenum, args[0]);
3702 err_code |= ERR_ALERT | ERR_FATAL;
3703 goto out;
3704 }
3705
3706 /* set the desired header name */
3707 free(curproxy->server_id_hdr_name);
3708 curproxy->server_id_hdr_name = strdup(args[1]);
3709 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3710 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003711 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003712 struct act_rule *rule;
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003713
Willy Tarreaub099aca2008-10-12 17:26:37 +02003714 if (curproxy == &defproxy) {
3715 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003716 err_code |= ERR_ALERT | ERR_FATAL;
3717 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003718 }
3719
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003720 /* emulate "block" using "http-request block". Since these rules are supposed to
3721 * be processed before all http-request rules, we put them into their own list
3722 * and will insert them at the end.
3723 */
3724 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3725 if (!rule) {
3726 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003727 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003728 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003729 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3730 err_code |= warnif_cond_conflicts(rule->cond,
3731 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3732 file, linenum);
3733 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003734
3735 if (!already_warned(WARN_BLOCK_DEPRECATED))
3736 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]);
3737
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003738 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003739 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003740 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003741
Cyril Bonté99ed3272010-01-24 23:29:44 +01003742 if (curproxy == &defproxy) {
3743 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3744 err_code |= ERR_ALERT | ERR_FATAL;
3745 goto out;
3746 }
3747
Willy Tarreaube4653b2015-05-28 15:26:58 +02003748 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003749 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3750 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003751 err_code |= ERR_ALERT | ERR_FATAL;
3752 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003753 }
3754
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003755 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003756 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003757 err_code |= warnif_cond_conflicts(rule->cond,
3758 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3759 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003760 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003761 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003762 struct switching_rule *rule;
3763
Willy Tarreaub099aca2008-10-12 17:26:37 +02003764 if (curproxy == &defproxy) {
3765 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003766 err_code |= ERR_ALERT | ERR_FATAL;
3767 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003768 }
3769
Willy Tarreau55ea7572007-06-17 19:56:27 +02003770 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003771 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003772
3773 if (*(args[1]) == 0) {
3774 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003775 err_code |= ERR_ALERT | ERR_FATAL;
3776 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003777 }
3778
Willy Tarreauf51658d2014-04-23 01:21:56 +02003779 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3780 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3781 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3782 file, linenum, errmsg);
3783 err_code |= ERR_ALERT | ERR_FATAL;
3784 goto out;
3785 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003786
Willy Tarreauf51658d2014-04-23 01:21:56 +02003787 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003788 }
3789
3790 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
3791 rule->cond = cond;
3792 rule->be.name = strdup(args[1]);
3793 LIST_INIT(&rule->list);
3794 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3795 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003796 else if (strcmp(args[0], "use-server") == 0) {
3797 struct server_rule *rule;
3798
3799 if (curproxy == &defproxy) {
3800 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3801 err_code |= ERR_ALERT | ERR_FATAL;
3802 goto out;
3803 }
3804
3805 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3806 err_code |= ERR_WARN;
3807
3808 if (*(args[1]) == 0) {
3809 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3810 err_code |= ERR_ALERT | ERR_FATAL;
3811 goto out;
3812 }
3813
3814 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3815 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3816 file, linenum, args[0]);
3817 err_code |= ERR_ALERT | ERR_FATAL;
3818 goto out;
3819 }
3820
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003821 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3822 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3823 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003824 err_code |= ERR_ALERT | ERR_FATAL;
3825 goto out;
3826 }
3827
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003828 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003829
3830 rule = (struct server_rule *)calloc(1, sizeof(*rule));
3831 rule->cond = cond;
3832 rule->srv.name = strdup(args[1]);
3833 LIST_INIT(&rule->list);
3834 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3835 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3836 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003837 else if ((!strcmp(args[0], "force-persist")) ||
3838 (!strcmp(args[0], "ignore-persist"))) {
3839 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003840
3841 if (curproxy == &defproxy) {
3842 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3843 err_code |= ERR_ALERT | ERR_FATAL;
3844 goto out;
3845 }
3846
3847 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3848 err_code |= ERR_WARN;
3849
Willy Tarreauef6494c2010-01-28 17:12:36 +01003850 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003851 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3852 file, linenum, args[0]);
3853 err_code |= ERR_ALERT | ERR_FATAL;
3854 goto out;
3855 }
3856
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003857 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3858 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3859 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003860 err_code |= ERR_ALERT | ERR_FATAL;
3861 goto out;
3862 }
3863
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003864 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3865 * where force-persist is applied.
3866 */
3867 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003868
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003869 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003870 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003871 if (!strcmp(args[0], "force-persist")) {
3872 rule->type = PERSIST_TYPE_FORCE;
3873 } else {
3874 rule->type = PERSIST_TYPE_IGNORE;
3875 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003876 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003877 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003878 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003879 else if (!strcmp(args[0], "stick-table")) {
3880 int myidx = 1;
Willy Tarreaue45288c2015-05-26 10:49:46 +02003881 struct proxy *other;
3882
Willy Tarreaue2dc1fa2015-05-26 12:08:07 +02003883 other = proxy_tbl_by_name(curproxy->id);
Willy Tarreaue45288c2015-05-26 10:49:46 +02003884 if (other) {
3885 Alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
3886 file, linenum, curproxy->id, proxy_type_str(other), other->id, other->conf.file, other->conf.line);
3887 err_code |= ERR_ALERT | ERR_FATAL;
3888 goto out;
3889 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003890
Emeric Brun32da3c42010-09-23 18:39:19 +02003891 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003892 curproxy->table.type = (unsigned int)-1;
3893 while (*args[myidx]) {
3894 const char *err;
3895
3896 if (strcmp(args[myidx], "size") == 0) {
3897 myidx++;
3898 if (!*(args[myidx])) {
3899 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3900 file, linenum, args[myidx-1]);
3901 err_code |= ERR_ALERT | ERR_FATAL;
3902 goto out;
3903 }
3904 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3905 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3906 file, linenum, *err, args[myidx-1]);
3907 err_code |= ERR_ALERT | ERR_FATAL;
3908 goto out;
3909 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003910 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003911 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003912 else if (strcmp(args[myidx], "peers") == 0) {
3913 myidx++;
Godbach50523162013-12-11 19:48:57 +08003914 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003915 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3916 file, linenum, args[myidx-1]);
3917 err_code |= ERR_ALERT | ERR_FATAL;
3918 goto out;
Godbach50523162013-12-11 19:48:57 +08003919 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003920 curproxy->table.peers.name = strdup(args[myidx++]);
3921 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003922 else if (strcmp(args[myidx], "expire") == 0) {
3923 myidx++;
3924 if (!*(args[myidx])) {
3925 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3926 file, linenum, args[myidx-1]);
3927 err_code |= ERR_ALERT | ERR_FATAL;
3928 goto out;
3929 }
3930 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3931 if (err) {
3932 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3933 file, linenum, *err, args[myidx-1]);
3934 err_code |= ERR_ALERT | ERR_FATAL;
3935 goto out;
3936 }
3937 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003938 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003939 }
3940 else if (strcmp(args[myidx], "nopurge") == 0) {
3941 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003942 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003943 }
3944 else if (strcmp(args[myidx], "type") == 0) {
3945 myidx++;
3946 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3947 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3948 file, linenum, args[myidx]);
3949 err_code |= ERR_ALERT | ERR_FATAL;
3950 goto out;
3951 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003952 /* myidx already points to next arg */
3953 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003954 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003955 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003956 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003957
3958 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003959 nw = args[myidx];
3960 while (*nw) {
3961 /* the "store" keyword supports a comma-separated list */
3962 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003963 sa = NULL; /* store arg */
3964 while (*nw && *nw != ',') {
3965 if (*nw == '(') {
3966 *nw = 0;
3967 sa = ++nw;
3968 while (*nw != ')') {
3969 if (!*nw) {
3970 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3971 file, linenum, args[0], cw);
3972 err_code |= ERR_ALERT | ERR_FATAL;
3973 goto out;
3974 }
3975 nw++;
3976 }
3977 *nw = '\0';
3978 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003979 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003980 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003981 if (*nw)
3982 *nw++ = '\0';
3983 type = stktable_get_data_type(cw);
3984 if (type < 0) {
3985 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3986 file, linenum, args[0], cw);
3987 err_code |= ERR_ALERT | ERR_FATAL;
3988 goto out;
3989 }
Willy Tarreauac782882010-06-20 10:41:54 +02003990
3991 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3992 switch (err) {
3993 case PE_NONE: break;
3994 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003995 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3996 file, linenum, args[0], cw);
3997 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003998 break;
3999
4000 case PE_ARG_MISSING:
4001 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
4002 file, linenum, args[0], cw);
4003 err_code |= ERR_ALERT | ERR_FATAL;
4004 goto out;
4005
4006 case PE_ARG_NOT_USED:
4007 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
4008 file, linenum, args[0], cw);
4009 err_code |= ERR_ALERT | ERR_FATAL;
4010 goto out;
4011
4012 default:
4013 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
4014 file, linenum, args[0], cw);
4015 err_code |= ERR_ALERT | ERR_FATAL;
4016 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004017 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004018 }
4019 myidx++;
4020 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004021 else {
4022 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
4023 file, linenum, args[myidx]);
4024 err_code |= ERR_ALERT | ERR_FATAL;
4025 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004026 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004027 }
4028
4029 if (!curproxy->table.size) {
4030 Alert("parsing [%s:%d] : stick-table: missing size.\n",
4031 file, linenum);
4032 err_code |= ERR_ALERT | ERR_FATAL;
4033 goto out;
4034 }
4035
4036 if (curproxy->table.type == (unsigned int)-1) {
4037 Alert("parsing [%s:%d] : stick-table: missing type.\n",
4038 file, linenum);
4039 err_code |= ERR_ALERT | ERR_FATAL;
4040 goto out;
4041 }
4042 }
4043 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004044 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02004045 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004046 int myidx = 0;
4047 const char *name = NULL;
4048 int flags;
4049
4050 if (curproxy == &defproxy) {
4051 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4052 err_code |= ERR_ALERT | ERR_FATAL;
4053 goto out;
4054 }
4055
4056 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
4057 err_code |= ERR_WARN;
4058 goto out;
4059 }
4060
4061 myidx++;
4062 if ((strcmp(args[myidx], "store") == 0) ||
4063 (strcmp(args[myidx], "store-request") == 0)) {
4064 myidx++;
4065 flags = STK_IS_STORE;
4066 }
4067 else if (strcmp(args[myidx], "store-response") == 0) {
4068 myidx++;
4069 flags = STK_IS_STORE | STK_ON_RSP;
4070 }
4071 else if (strcmp(args[myidx], "match") == 0) {
4072 myidx++;
4073 flags = STK_IS_MATCH;
4074 }
4075 else if (strcmp(args[myidx], "on") == 0) {
4076 myidx++;
4077 flags = STK_IS_MATCH | STK_IS_STORE;
4078 }
4079 else {
4080 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
4081 err_code |= ERR_ALERT | ERR_FATAL;
4082 goto out;
4083 }
4084
4085 if (*(args[myidx]) == 0) {
4086 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
4087 err_code |= ERR_ALERT | ERR_FATAL;
4088 goto out;
4089 }
4090
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004091 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01004092 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004093 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01004094 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004095 err_code |= ERR_ALERT | ERR_FATAL;
4096 goto out;
4097 }
4098
4099 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01004100 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
4101 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
4102 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004103 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004104 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004105 goto out;
4106 }
4107 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01004108 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
4109 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
4110 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004111 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004112 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004113 goto out;
4114 }
4115 }
4116
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004117 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01004118 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004119
Emeric Brunb982a3d2010-01-04 15:45:53 +01004120 if (strcmp(args[myidx], "table") == 0) {
4121 myidx++;
4122 name = args[myidx++];
4123 }
4124
Willy Tarreauef6494c2010-01-28 17:12:36 +01004125 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004126 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
4127 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
4128 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004129 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004130 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004131 goto out;
4132 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004133 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01004134 else if (*(args[myidx])) {
4135 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
4136 file, linenum, args[0], args[myidx]);
4137 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004138 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01004139 goto out;
4140 }
Emeric Brun97679e72010-09-23 17:56:44 +02004141 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004142 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02004143 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004144 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01004145
Emeric Brunb982a3d2010-01-04 15:45:53 +01004146 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
4147 rule->cond = cond;
4148 rule->expr = expr;
4149 rule->flags = flags;
4150 rule->table.name = name ? strdup(name) : NULL;
4151 LIST_INIT(&rule->list);
4152 if (flags & STK_ON_RSP)
4153 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
4154 else
4155 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
4156 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004157 else if (!strcmp(args[0], "stats")) {
4158 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
4159 curproxy->uri_auth = NULL; /* we must detach from the default config */
4160
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004161 if (!*args[1]) {
4162 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02004163 } else if (!strcmp(args[1], "admin")) {
4164 struct stats_admin_rule *rule;
4165
4166 if (curproxy == &defproxy) {
4167 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
4168 err_code |= ERR_ALERT | ERR_FATAL;
4169 goto out;
4170 }
4171
4172 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4173 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4174 err_code |= ERR_ALERT | ERR_ABORT;
4175 goto out;
4176 }
4177
4178 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4179 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4180 file, linenum, args[0], args[1]);
4181 err_code |= ERR_ALERT | ERR_FATAL;
4182 goto out;
4183 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004184 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4185 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
4186 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02004187 err_code |= ERR_ALERT | ERR_FATAL;
4188 goto out;
4189 }
4190
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004191 err_code |= warnif_cond_conflicts(cond,
4192 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4193 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02004194
4195 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
4196 rule->cond = cond;
4197 LIST_INIT(&rule->list);
4198 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004199 } else if (!strcmp(args[1], "uri")) {
4200 if (*(args[2]) == 0) {
4201 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004202 err_code |= ERR_ALERT | ERR_FATAL;
4203 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004204 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
4205 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004206 err_code |= ERR_ALERT | ERR_ABORT;
4207 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004208 }
4209 } else if (!strcmp(args[1], "realm")) {
4210 if (*(args[2]) == 0) {
4211 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004212 err_code |= ERR_ALERT | ERR_FATAL;
4213 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004214 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
4215 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004216 err_code |= ERR_ALERT | ERR_ABORT;
4217 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004218 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02004219 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004220 unsigned interval;
4221
4222 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
4223 if (err) {
4224 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
4225 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004226 err_code |= ERR_ALERT | ERR_FATAL;
4227 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004228 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
4229 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004230 err_code |= ERR_ALERT | ERR_ABORT;
4231 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004232 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004233 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004234 struct act_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004235
4236 if (curproxy == &defproxy) {
4237 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4238 err_code |= ERR_ALERT | ERR_FATAL;
4239 goto out;
4240 }
4241
4242 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4243 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4244 err_code |= ERR_ALERT | ERR_ABORT;
4245 goto out;
4246 }
4247
Willy Tarreauff011f22011-01-06 17:51:27 +01004248 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004249 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct act_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004250 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
4251 file, linenum, args[0]);
4252 err_code |= ERR_WARN;
4253 }
4254
Willy Tarreauff011f22011-01-06 17:51:27 +01004255 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004256
Willy Tarreauff011f22011-01-06 17:51:27 +01004257 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004258 err_code |= ERR_ALERT | ERR_ABORT;
4259 goto out;
4260 }
4261
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004262 err_code |= warnif_cond_conflicts(rule->cond,
4263 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4264 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01004265 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004266
Willy Tarreaubaaee002006-06-26 02:48:02 +02004267 } else if (!strcmp(args[1], "auth")) {
4268 if (*(args[2]) == 0) {
4269 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004270 err_code |= ERR_ALERT | ERR_FATAL;
4271 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004272 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
4273 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004274 err_code |= ERR_ALERT | ERR_ABORT;
4275 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004276 }
4277 } else if (!strcmp(args[1], "scope")) {
4278 if (*(args[2]) == 0) {
4279 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004280 err_code |= ERR_ALERT | ERR_FATAL;
4281 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004282 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
4283 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004284 err_code |= ERR_ALERT | ERR_ABORT;
4285 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004286 }
4287 } else if (!strcmp(args[1], "enable")) {
4288 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4289 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004290 err_code |= ERR_ALERT | ERR_ABORT;
4291 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004292 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004293 } else if (!strcmp(args[1], "hide-version")) {
4294 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
4295 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004296 err_code |= ERR_ALERT | ERR_ABORT;
4297 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004298 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01004299 } else if (!strcmp(args[1], "show-legends")) {
4300 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
4301 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4302 err_code |= ERR_ALERT | ERR_ABORT;
4303 goto out;
4304 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004305 } else if (!strcmp(args[1], "show-node")) {
4306
4307 if (*args[2]) {
4308 int i;
4309 char c;
4310
4311 for (i=0; args[2][i]; i++) {
4312 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01004313 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
4314 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004315 break;
4316 }
4317
4318 if (!i || args[2][i]) {
4319 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
4320 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
4321 file, linenum, args[0], args[1]);
4322 err_code |= ERR_ALERT | ERR_FATAL;
4323 goto out;
4324 }
4325 }
4326
4327 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
4328 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4329 err_code |= ERR_ALERT | ERR_ABORT;
4330 goto out;
4331 }
4332 } else if (!strcmp(args[1], "show-desc")) {
4333 char *desc = NULL;
4334
4335 if (*args[2]) {
4336 int i, len=0;
4337 char *d;
4338
Willy Tarreau348acfe2014-04-14 15:00:39 +02004339 for (i = 2; *args[i]; i++)
4340 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004341
4342 desc = d = (char *)calloc(1, len);
4343
Willy Tarreau348acfe2014-04-14 15:00:39 +02004344 d += snprintf(d, desc + len - d, "%s", args[2]);
4345 for (i = 3; *args[i]; i++)
4346 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004347 }
4348
4349 if (!*args[2] && !global.desc)
4350 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
4351 file, linenum, args[1]);
4352 else {
4353 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
4354 free(desc);
4355 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4356 err_code |= ERR_ALERT | ERR_ABORT;
4357 goto out;
4358 }
4359 free(desc);
4360 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004361 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004362stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02004363 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 +01004364 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004365 err_code |= ERR_ALERT | ERR_FATAL;
4366 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004367 }
4368 }
4369 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004370 int optnum;
4371
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004372 if (*(args[1]) == '\0') {
4373 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
4374 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004375 err_code |= ERR_ALERT | ERR_FATAL;
4376 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004377 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01004378
4379 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
4380 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004381 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
4382 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4383 file, linenum, cfg_opts[optnum].name);
4384 err_code |= ERR_ALERT | ERR_FATAL;
4385 goto out;
4386 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004387 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4388 goto out;
4389
Willy Tarreau93893792009-07-23 13:19:11 +02004390 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
4391 err_code |= ERR_WARN;
4392 goto out;
4393 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004394
Willy Tarreau3842f002009-06-14 11:39:52 +02004395 curproxy->no_options &= ~cfg_opts[optnum].val;
4396 curproxy->options &= ~cfg_opts[optnum].val;
4397
4398 switch (kwm) {
4399 case KWM_STD:
4400 curproxy->options |= cfg_opts[optnum].val;
4401 break;
4402 case KWM_NO:
4403 curproxy->no_options |= cfg_opts[optnum].val;
4404 break;
4405 case KWM_DEF: /* already cleared */
4406 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004407 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004408
Willy Tarreau93893792009-07-23 13:19:11 +02004409 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004410 }
4411 }
4412
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004413 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
4414 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004415 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
4416 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4417 file, linenum, cfg_opts2[optnum].name);
4418 err_code |= ERR_ALERT | ERR_FATAL;
4419 goto out;
4420 }
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 Tarreau93893792009-07-23 13:19:11 +02004423 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4424 err_code |= ERR_WARN;
4425 goto out;
4426 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004427
Willy Tarreau3842f002009-06-14 11:39:52 +02004428 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4429 curproxy->options2 &= ~cfg_opts2[optnum].val;
4430
4431 switch (kwm) {
4432 case KWM_STD:
4433 curproxy->options2 |= cfg_opts2[optnum].val;
4434 break;
4435 case KWM_NO:
4436 curproxy->no_options2 |= cfg_opts2[optnum].val;
4437 break;
4438 case KWM_DEF: /* already cleared */
4439 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004440 }
Willy Tarreau93893792009-07-23 13:19:11 +02004441 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004442 }
4443 }
4444
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004445 /* HTTP options override each other. They can be cancelled using
4446 * "no option xxx" which only switches to default mode if the mode
4447 * was this one (useful for cancelling options set in defaults
4448 * sections).
4449 */
4450 if (strcmp(args[1], "httpclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004451 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4452 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004453 if (kwm == KWM_STD) {
4454 curproxy->options &= ~PR_O_HTTP_MODE;
4455 curproxy->options |= PR_O_HTTP_PCL;
4456 goto out;
4457 }
4458 else if (kwm == KWM_NO) {
4459 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4460 curproxy->options &= ~PR_O_HTTP_MODE;
4461 goto out;
4462 }
4463 }
4464 else if (strcmp(args[1], "forceclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004465 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4466 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004467 if (kwm == KWM_STD) {
4468 curproxy->options &= ~PR_O_HTTP_MODE;
4469 curproxy->options |= PR_O_HTTP_FCL;
4470 goto out;
4471 }
4472 else if (kwm == KWM_NO) {
4473 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4474 curproxy->options &= ~PR_O_HTTP_MODE;
4475 goto out;
4476 }
4477 }
4478 else if (strcmp(args[1], "http-server-close") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004479 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4480 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004481 if (kwm == KWM_STD) {
4482 curproxy->options &= ~PR_O_HTTP_MODE;
4483 curproxy->options |= PR_O_HTTP_SCL;
4484 goto out;
4485 }
4486 else if (kwm == KWM_NO) {
4487 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4488 curproxy->options &= ~PR_O_HTTP_MODE;
4489 goto out;
4490 }
4491 }
4492 else if (strcmp(args[1], "http-keep-alive") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004493 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4494 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004495 if (kwm == KWM_STD) {
4496 curproxy->options &= ~PR_O_HTTP_MODE;
4497 curproxy->options |= PR_O_HTTP_KAL;
4498 goto out;
4499 }
4500 else if (kwm == KWM_NO) {
4501 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4502 curproxy->options &= ~PR_O_HTTP_MODE;
4503 goto out;
4504 }
4505 }
4506 else if (strcmp(args[1], "http-tunnel") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004507 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4508 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004509 if (kwm == KWM_STD) {
4510 curproxy->options &= ~PR_O_HTTP_MODE;
4511 curproxy->options |= PR_O_HTTP_TUN;
4512 goto out;
4513 }
4514 else if (kwm == KWM_NO) {
4515 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4516 curproxy->options &= ~PR_O_HTTP_MODE;
4517 goto out;
4518 }
4519 }
4520
Joseph Lynch726ab712015-05-11 23:25:34 -07004521 /* Redispatch can take an integer argument that control when the
4522 * resispatch occurs. All values are relative to the retries option.
4523 * This can be cancelled using "no option xxx".
4524 */
4525 if (strcmp(args[1], "redispatch") == 0) {
4526 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
4527 err_code |= ERR_WARN;
4528 goto out;
4529 }
4530
4531 curproxy->no_options &= ~PR_O_REDISP;
4532 curproxy->options &= ~PR_O_REDISP;
4533
4534 switch (kwm) {
4535 case KWM_STD:
4536 curproxy->options |= PR_O_REDISP;
4537 curproxy->redispatch_after = -1;
4538 if(*args[2]) {
4539 curproxy->redispatch_after = atol(args[2]);
4540 }
4541 break;
4542 case KWM_NO:
4543 curproxy->no_options |= PR_O_REDISP;
4544 curproxy->redispatch_after = 0;
4545 break;
4546 case KWM_DEF: /* already cleared */
4547 break;
4548 }
4549 goto out;
4550 }
4551
Willy Tarreau3842f002009-06-14 11:39:52 +02004552 if (kwm != KWM_STD) {
4553 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004554 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004555 err_code |= ERR_ALERT | ERR_FATAL;
4556 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004557 }
4558
Emeric Brun3a058f32009-06-30 18:26:00 +02004559 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004560 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004561 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004562 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004563 if (*(args[2]) != '\0') {
4564 if (!strcmp(args[2], "clf")) {
4565 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004566 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004567 } else {
William Lallemand77063bc2015-05-28 18:02:48 +02004568 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004569 err_code |= ERR_ALERT | ERR_FATAL;
4570 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004571 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004572 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
4573 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004574 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004575 if (curproxy->conf.logformat_string != default_http_log_format &&
4576 curproxy->conf.logformat_string != default_tcp_log_format &&
4577 curproxy->conf.logformat_string != clf_http_log_format)
4578 free(curproxy->conf.logformat_string);
4579 curproxy->conf.logformat_string = logformat;
4580
4581 free(curproxy->conf.lfs_file);
4582 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4583 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004584 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004585 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004586 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004587 if (curproxy->conf.logformat_string != default_http_log_format &&
4588 curproxy->conf.logformat_string != default_tcp_log_format &&
4589 curproxy->conf.logformat_string != clf_http_log_format)
4590 free(curproxy->conf.logformat_string);
4591 curproxy->conf.logformat_string = default_tcp_log_format;
4592
4593 free(curproxy->conf.lfs_file);
4594 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4595 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemanddf1425a2015-04-28 20:17:49 +02004596
4597 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4598 goto out;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004599 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004600 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004601 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004602 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004603 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004604
William Lallemanddf1425a2015-04-28 20:17:49 +02004605 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4606 goto out;
4607
Willy Tarreau13943ab2006-12-31 00:24:10 +01004608 if (curproxy->cap & PR_CAP_FE)
4609 curproxy->options |= PR_O_TCP_CLI_KA;
4610 if (curproxy->cap & PR_CAP_BE)
4611 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004612 }
4613 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004614 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004615 err_code |= ERR_WARN;
4616
Willy Tarreaubaaee002006-06-26 02:48:02 +02004617 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004618 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004619 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004620 curproxy->options2 &= ~PR_O2_CHK_ANY;
4621 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004622 if (!*args[2]) { /* no argument */
4623 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4624 curproxy->check_len = strlen(DEF_CHECK_REQ);
4625 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004626 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004627 curproxy->check_req = (char *)malloc(reqlen);
4628 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004629 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004630 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004631 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004632 if (*args[4])
4633 reqlen += strlen(args[4]);
4634 else
4635 reqlen += strlen("HTTP/1.0");
4636
4637 curproxy->check_req = (char *)malloc(reqlen);
4638 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004639 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004640 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004641 if (alertif_too_many_args_idx(3, 1, file, linenum, args, &err_code))
4642 goto out;
Willy Tarreauf3c69202006-07-09 16:42:34 +02004643 }
4644 else if (!strcmp(args[1], "ssl-hello-chk")) {
4645 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004646 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004647 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004648
Willy Tarreaua534fea2008-08-03 12:19:50 +02004649 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004650 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004651 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004652 curproxy->options2 |= PR_O2_SSL3_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004653
4654 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4655 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004656 }
Willy Tarreau23677902007-05-08 23:50:35 +02004657 else if (!strcmp(args[1], "smtpchk")) {
4658 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004659 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004660 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004661 curproxy->options2 &= ~PR_O2_CHK_ANY;
4662 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004663
4664 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4665 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4666 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4667 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4668 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4669 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
4670 curproxy->check_req = (char *)malloc(reqlen);
4671 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4672 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4673 } else {
4674 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4675 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4676 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4677 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4678 }
4679 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004680 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4681 goto out;
Willy Tarreau23677902007-05-08 23:50:35 +02004682 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004683 else if (!strcmp(args[1], "pgsql-check")) {
4684 /* use PostgreSQL request to check servers' health */
4685 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4686 err_code |= ERR_WARN;
4687
4688 free(curproxy->check_req);
4689 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004690 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004691 curproxy->options2 |= PR_O2_PGSQL_CHK;
4692
4693 if (*(args[2])) {
4694 int cur_arg = 2;
4695
4696 while (*(args[cur_arg])) {
4697 if (strcmp(args[cur_arg], "user") == 0) {
4698 char * packet;
4699 uint32_t packet_len;
4700 uint32_t pv;
4701
4702 /* suboption header - needs additional argument for it */
4703 if (*(args[cur_arg+1]) == 0) {
4704 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4705 file, linenum, args[0], args[1], args[cur_arg]);
4706 err_code |= ERR_ALERT | ERR_FATAL;
4707 goto out;
4708 }
4709
4710 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4711 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4712 pv = htonl(0x30000); /* protocol version 3.0 */
4713
4714 packet = (char*) calloc(1, packet_len);
4715
4716 memcpy(packet + 4, &pv, 4);
4717
4718 /* copy "user" */
4719 memcpy(packet + 8, "user", 4);
4720
4721 /* copy username */
4722 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4723
4724 free(curproxy->check_req);
4725 curproxy->check_req = packet;
4726 curproxy->check_len = packet_len;
4727
4728 packet_len = htonl(packet_len);
4729 memcpy(packet, &packet_len, 4);
4730 cur_arg += 2;
4731 } else {
4732 /* unknown suboption - catchall */
4733 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4734 file, linenum, args[0], args[1]);
4735 err_code |= ERR_ALERT | ERR_FATAL;
4736 goto out;
4737 }
4738 } /* end while loop */
4739 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004740 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4741 goto out;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004742 }
4743
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004744 else if (!strcmp(args[1], "redis-check")) {
4745 /* use REDIS PING request to check servers' health */
4746 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4747 err_code |= ERR_WARN;
4748
4749 free(curproxy->check_req);
4750 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004751 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004752 curproxy->options2 |= PR_O2_REDIS_CHK;
4753
4754 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
4755 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4756 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004757
4758 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4759 goto out;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004760 }
4761
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004762 else if (!strcmp(args[1], "mysql-check")) {
4763 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004764 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4765 err_code |= ERR_WARN;
4766
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004767 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004768 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004769 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004770 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004771
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004772 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004773 * const char mysql40_client_auth_pkt[] = {
4774 * "\x0e\x00\x00" // packet length
4775 * "\x01" // packet number
4776 * "\x00\x00" // client capabilities
4777 * "\x00\x00\x01" // max packet
4778 * "haproxy\x00" // username (null terminated string)
4779 * "\x00" // filler (always 0x00)
4780 * "\x01\x00\x00" // packet length
4781 * "\x00" // packet number
4782 * "\x01" // COM_QUIT command
4783 * };
4784 */
4785
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004786 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4787 * const char mysql41_client_auth_pkt[] = {
4788 * "\x0e\x00\x00\" // packet length
4789 * "\x01" // packet number
4790 * "\x00\x00\x00\x00" // client capabilities
4791 * "\x00\x00\x00\x01" // max packet
4792 * "\x21" // character set (UTF-8)
4793 * char[23] // All zeroes
4794 * "haproxy\x00" // username (null terminated string)
4795 * "\x00" // filler (always 0x00)
4796 * "\x01\x00\x00" // packet length
4797 * "\x00" // packet number
4798 * "\x01" // COM_QUIT command
4799 * };
4800 */
4801
4802
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004803 if (*(args[2])) {
4804 int cur_arg = 2;
4805
4806 while (*(args[cur_arg])) {
4807 if (strcmp(args[cur_arg], "user") == 0) {
4808 char *mysqluser;
4809 int packetlen, reqlen, userlen;
4810
4811 /* suboption header - needs additional argument for it */
4812 if (*(args[cur_arg+1]) == 0) {
4813 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4814 file, linenum, args[0], args[1], args[cur_arg]);
4815 err_code |= ERR_ALERT | ERR_FATAL;
4816 goto out;
4817 }
4818 mysqluser = args[cur_arg + 1];
4819 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004820
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004821 if (*(args[cur_arg+2])) {
4822 if (!strcmp(args[cur_arg+2], "post-41")) {
4823 packetlen = userlen + 7 + 27;
4824 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004825
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004826 free(curproxy->check_req);
4827 curproxy->check_req = (char *)calloc(1, reqlen);
4828 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004829
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004830 snprintf(curproxy->check_req, 4, "%c%c%c",
4831 ((unsigned char) packetlen & 0xff),
4832 ((unsigned char) (packetlen >> 8) & 0xff),
4833 ((unsigned char) (packetlen >> 16) & 0xff));
4834
4835 curproxy->check_req[3] = 1;
4836 curproxy->check_req[5] = 130;
4837 curproxy->check_req[11] = 1;
4838 curproxy->check_req[12] = 33;
4839 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4840 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4841 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4842 cur_arg += 3;
4843 } else {
4844 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4845 err_code |= ERR_ALERT | ERR_FATAL;
4846 goto out;
4847 }
4848 } else {
4849 packetlen = userlen + 7;
4850 reqlen = packetlen + 9;
4851
4852 free(curproxy->check_req);
4853 curproxy->check_req = (char *)calloc(1, reqlen);
4854 curproxy->check_len = reqlen;
4855
4856 snprintf(curproxy->check_req, 4, "%c%c%c",
4857 ((unsigned char) packetlen & 0xff),
4858 ((unsigned char) (packetlen >> 8) & 0xff),
4859 ((unsigned char) (packetlen >> 16) & 0xff));
4860
4861 curproxy->check_req[3] = 1;
4862 curproxy->check_req[5] = 128;
4863 curproxy->check_req[8] = 1;
4864 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4865 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4866 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4867 cur_arg += 2;
4868 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004869 } else {
4870 /* unknown suboption - catchall */
4871 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4872 file, linenum, args[0], args[1]);
4873 err_code |= ERR_ALERT | ERR_FATAL;
4874 goto out;
4875 }
4876 } /* end while loop */
4877 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004878 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004879 else if (!strcmp(args[1], "ldap-check")) {
4880 /* use LDAP request to check servers' health */
4881 free(curproxy->check_req);
4882 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004883 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004884 curproxy->options2 |= PR_O2_LDAP_CHK;
4885
4886 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
4887 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
4888 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004889 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4890 goto out;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004891 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004892 else if (!strcmp(args[1], "tcp-check")) {
4893 /* use raw TCPCHK send/expect to check servers' health */
4894 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4895 err_code |= ERR_WARN;
4896
4897 free(curproxy->check_req);
4898 curproxy->check_req = NULL;
4899 curproxy->options2 &= ~PR_O2_CHK_ANY;
4900 curproxy->options2 |= PR_O2_TCPCHK_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004901 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4902 goto out;
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004903 }
Simon Horman98637e52014-06-20 12:30:16 +09004904 else if (!strcmp(args[1], "external-check")) {
4905 /* excute an external command to check servers' health */
4906 free(curproxy->check_req);
4907 curproxy->check_req = NULL;
4908 curproxy->options2 &= ~PR_O2_CHK_ANY;
4909 curproxy->options2 |= PR_O2_EXT_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004910 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4911 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09004912 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004913 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004914 int cur_arg;
4915
4916 /* insert x-forwarded-for field, but not for the IP address listed as an except.
4917 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004918 */
Ross Westaf72a1d2008-08-03 10:51:45 +02004919
Willy Tarreau87cf5142011-08-19 22:57:24 +02004920 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02004921
4922 free(curproxy->fwdfor_hdr_name);
4923 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
4924 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
4925
4926 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
4927 cur_arg = 2;
4928 while (*(args[cur_arg])) {
4929 if (!strcmp(args[cur_arg], "except")) {
4930 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004931 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004932 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4933 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004934 err_code |= ERR_ALERT | ERR_FATAL;
4935 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004936 }
4937 /* flush useless bits */
4938 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02004939 cur_arg += 2;
4940 } else if (!strcmp(args[cur_arg], "header")) {
4941 /* suboption header - needs additional argument for it */
4942 if (*(args[cur_arg+1]) == 0) {
4943 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4944 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004945 err_code |= ERR_ALERT | ERR_FATAL;
4946 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02004947 }
4948 free(curproxy->fwdfor_hdr_name);
4949 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
4950 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
4951 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02004952 } else if (!strcmp(args[cur_arg], "if-none")) {
4953 curproxy->options &= ~PR_O_FF_ALWAYS;
4954 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004955 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02004956 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02004957 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02004958 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004959 err_code |= ERR_ALERT | ERR_FATAL;
4960 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004961 }
Ross Westaf72a1d2008-08-03 10:51:45 +02004962 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004963 }
Maik Broemme2850cb42009-04-17 18:53:21 +02004964 else if (!strcmp(args[1], "originalto")) {
4965 int cur_arg;
4966
4967 /* insert x-original-to field, but not for the IP address listed as an except.
4968 * set default options (ie: bitfield, header name, etc)
4969 */
4970
4971 curproxy->options |= PR_O_ORGTO;
4972
4973 free(curproxy->orgto_hdr_name);
4974 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
4975 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
4976
Willy Tarreau87cf5142011-08-19 22:57:24 +02004977 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02004978 cur_arg = 2;
4979 while (*(args[cur_arg])) {
4980 if (!strcmp(args[cur_arg], "except")) {
4981 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004982 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 +02004983 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4984 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004985 err_code |= ERR_ALERT | ERR_FATAL;
4986 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004987 }
4988 /* flush useless bits */
4989 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
4990 cur_arg += 2;
4991 } else if (!strcmp(args[cur_arg], "header")) {
4992 /* suboption header - needs additional argument for it */
4993 if (*(args[cur_arg+1]) == 0) {
4994 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4995 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004996 err_code |= ERR_ALERT | ERR_FATAL;
4997 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004998 }
4999 free(curproxy->orgto_hdr_name);
5000 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
5001 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
5002 cur_arg += 2;
5003 } else {
5004 /* unknown suboption - catchall */
5005 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
5006 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005007 err_code |= ERR_ALERT | ERR_FATAL;
5008 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005009 }
5010 } /* end while loop */
5011 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005012 else {
5013 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005014 err_code |= ERR_ALERT | ERR_FATAL;
5015 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005016 }
Willy Tarreau93893792009-07-23 13:19:11 +02005017 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005018 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005019 else if (!strcmp(args[0], "default_backend")) {
5020 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005021 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005022
5023 if (*(args[1]) == 0) {
5024 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005025 err_code |= ERR_ALERT | ERR_FATAL;
5026 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005027 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005028 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005029 curproxy->defbe.name = strdup(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005030
5031 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5032 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005033 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005034 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01005035 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005036 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005037
Willy Tarreaua3c504c2014-04-28 22:37:32 +02005038 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
5039 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 +01005040 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005041 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005042 /* enable reconnections to dispatch */
5043 curproxy->options |= PR_O_REDISP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005044
5045 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5046 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005047 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005048 else if (!strcmp(args[0], "http-reuse")) {
5049 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5050 err_code |= ERR_WARN;
5051
5052 if (strcmp(args[1], "never") == 0) {
5053 /* enable a graceful server shutdown on an HTTP 404 response */
5054 curproxy->options &= ~PR_O_REUSE_MASK;
5055 curproxy->options |= PR_O_REUSE_NEVR;
5056 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5057 goto out;
5058 }
Willy Tarreau161d45f2015-08-05 16:02:46 +02005059 else if (strcmp(args[1], "safe") == 0) {
5060 /* enable a graceful server shutdown on an HTTP 404 response */
5061 curproxy->options &= ~PR_O_REUSE_MASK;
5062 curproxy->options |= PR_O_REUSE_SAFE;
5063 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5064 goto out;
5065 }
Willy Tarreau449d74a2015-08-05 17:16:33 +02005066 else if (strcmp(args[1], "aggressive") == 0) {
5067 curproxy->options &= ~PR_O_REUSE_MASK;
5068 curproxy->options |= PR_O_REUSE_AGGR;
5069 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5070 goto out;
5071 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005072 else if (strcmp(args[1], "always") == 0) {
5073 /* enable a graceful server shutdown on an HTTP 404 response */
5074 curproxy->options &= ~PR_O_REUSE_MASK;
5075 curproxy->options |= PR_O_REUSE_ALWS;
5076 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5077 goto out;
5078 }
5079 else {
Willy Tarreau449d74a2015-08-05 17:16:33 +02005080 Alert("parsing [%s:%d] : '%s' only supports 'never', 'safe', 'aggressive', 'always'.\n", file, linenum, args[0]);
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005081 err_code |= ERR_ALERT | ERR_FATAL;
5082 goto out;
5083 }
5084 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005085 else if (!strcmp(args[0], "http-check")) {
5086 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005087 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01005088
5089 if (strcmp(args[1], "disable-on-404") == 0) {
5090 /* enable a graceful server shutdown on an HTTP 404 response */
5091 curproxy->options |= PR_O_DISABLE404;
William Lallemanddf1425a2015-04-28 20:17:49 +02005092 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5093 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005094 }
Willy Tarreauef781042010-01-27 11:53:01 +01005095 else if (strcmp(args[1], "send-state") == 0) {
5096 /* enable emission of the apparent state of a server in HTTP checks */
5097 curproxy->options2 |= PR_O2_CHK_SNDST;
William Lallemanddf1425a2015-04-28 20:17:49 +02005098 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5099 goto out;
Willy Tarreauef781042010-01-27 11:53:01 +01005100 }
Willy Tarreaubd741542010-03-16 18:46:54 +01005101 else if (strcmp(args[1], "expect") == 0) {
5102 const char *ptr_arg;
5103 int cur_arg;
5104
5105 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5106 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5107 err_code |= ERR_ALERT | ERR_FATAL;
5108 goto out;
5109 }
5110
5111 cur_arg = 2;
5112 /* consider exclamation marks, sole or at the beginning of a word */
5113 while (*(ptr_arg = args[cur_arg])) {
5114 while (*ptr_arg == '!') {
5115 curproxy->options2 ^= PR_O2_EXP_INV;
5116 ptr_arg++;
5117 }
5118 if (*ptr_arg)
5119 break;
5120 cur_arg++;
5121 }
5122 /* now ptr_arg points to the beginning of a word past any possible
5123 * exclamation mark, and cur_arg is the argument which holds this word.
5124 */
5125 if (strcmp(ptr_arg, "status") == 0) {
5126 if (!*(args[cur_arg + 1])) {
5127 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5128 file, linenum, args[0], args[1], ptr_arg);
5129 err_code |= ERR_ALERT | ERR_FATAL;
5130 goto out;
5131 }
5132 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005133 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005134 curproxy->expect_str = strdup(args[cur_arg + 1]);
5135 }
5136 else if (strcmp(ptr_arg, "string") == 0) {
5137 if (!*(args[cur_arg + 1])) {
5138 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5139 file, linenum, args[0], args[1], ptr_arg);
5140 err_code |= ERR_ALERT | ERR_FATAL;
5141 goto out;
5142 }
5143 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005144 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005145 curproxy->expect_str = strdup(args[cur_arg + 1]);
5146 }
5147 else if (strcmp(ptr_arg, "rstatus") == 0) {
5148 if (!*(args[cur_arg + 1])) {
5149 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5150 file, linenum, args[0], args[1], ptr_arg);
5151 err_code |= ERR_ALERT | ERR_FATAL;
5152 goto out;
5153 }
5154 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005155 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005156 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005157 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005158 free(curproxy->expect_regex);
5159 curproxy->expect_regex = NULL;
5160 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005161 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005162 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5163 error = NULL;
5164 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5165 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5166 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5167 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005168 err_code |= ERR_ALERT | ERR_FATAL;
5169 goto out;
5170 }
5171 }
5172 else if (strcmp(ptr_arg, "rstring") == 0) {
5173 if (!*(args[cur_arg + 1])) {
5174 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5175 file, linenum, args[0], args[1], ptr_arg);
5176 err_code |= ERR_ALERT | ERR_FATAL;
5177 goto out;
5178 }
5179 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005180 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005181 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005182 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005183 free(curproxy->expect_regex);
5184 curproxy->expect_regex = NULL;
5185 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005186 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005187 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5188 error = NULL;
5189 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5190 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5191 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5192 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005193 err_code |= ERR_ALERT | ERR_FATAL;
5194 goto out;
5195 }
5196 }
5197 else {
5198 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
5199 file, linenum, args[0], args[1], ptr_arg);
5200 err_code |= ERR_ALERT | ERR_FATAL;
5201 goto out;
5202 }
5203 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005204 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005205 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 +02005206 err_code |= ERR_ALERT | ERR_FATAL;
5207 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005208 }
5209 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005210 else if (!strcmp(args[0], "tcp-check")) {
5211 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5212 err_code |= ERR_WARN;
5213
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005214 if (strcmp(args[1], "comment") == 0) {
5215 int cur_arg;
5216 struct tcpcheck_rule *tcpcheck;
5217
5218 cur_arg = 1;
5219 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5220 tcpcheck->action = TCPCHK_ACT_COMMENT;
5221
5222 if (!*args[cur_arg + 1]) {
5223 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5224 file, linenum, args[cur_arg]);
5225 err_code |= ERR_ALERT | ERR_FATAL;
5226 goto out;
5227 }
5228
5229 tcpcheck->comment = strdup(args[cur_arg + 1]);
5230
5231 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
William Lallemanddf1425a2015-04-28 20:17:49 +02005232 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
5233 goto out;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005234 }
5235 else if (strcmp(args[1], "connect") == 0) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005236 const char *ptr_arg;
5237 int cur_arg;
5238 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005239
5240 /* check if first rule is also a 'connect' action */
Willy Tarreau5581c272015-05-13 12:24:53 +02005241 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
5242 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
5243 tcpcheck->action == TCPCHK_ACT_COMMENT) {
5244 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
5245 }
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005246
Willy Tarreau5581c272015-05-13 12:24:53 +02005247 if (&tcpcheck->list != &curproxy->tcpcheck_rules
5248 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
5249 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
5250 file, linenum);
5251 err_code |= ERR_ALERT | ERR_FATAL;
5252 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005253 }
5254
5255 cur_arg = 2;
5256 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5257 tcpcheck->action = TCPCHK_ACT_CONNECT;
5258
5259 /* parsing each parameters to fill up the rule */
5260 while (*(ptr_arg = args[cur_arg])) {
5261 /* tcp port */
5262 if (strcmp(args[cur_arg], "port") == 0) {
5263 if ( (atol(args[cur_arg + 1]) > 65535) ||
5264 (atol(args[cur_arg + 1]) < 1) ){
5265 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
5266 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
5267 err_code |= ERR_ALERT | ERR_FATAL;
5268 goto out;
5269 }
5270 tcpcheck->port = atol(args[cur_arg + 1]);
5271 cur_arg += 2;
5272 }
5273 /* send proxy protocol */
5274 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
5275 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
5276 cur_arg++;
5277 }
5278#ifdef USE_OPENSSL
5279 else if (strcmp(args[cur_arg], "ssl") == 0) {
5280 curproxy->options |= PR_O_TCPCHK_SSL;
5281 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
5282 cur_arg++;
5283 }
5284#endif /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005285 /* comment for this tcpcheck line */
5286 else if (strcmp(args[cur_arg], "comment") == 0) {
5287 if (!*args[cur_arg + 1]) {
5288 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5289 file, linenum, args[cur_arg]);
5290 err_code |= ERR_ALERT | ERR_FATAL;
5291 goto out;
5292 }
5293 tcpcheck->comment = strdup(args[cur_arg + 1]);
5294 cur_arg += 2;
5295 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005296 else {
5297#ifdef USE_OPENSSL
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005298 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 +01005299#else /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005300 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 +01005301#endif /* USE_OPENSSL */
5302 file, linenum, args[0], args[1], args[cur_arg]);
5303 err_code |= ERR_ALERT | ERR_FATAL;
5304 goto out;
5305 }
5306
5307 }
5308
5309 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5310 }
5311 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005312 if (! *(args[2]) ) {
5313 /* SEND string expected */
5314 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
5315 file, linenum, args[0], args[1], args[2]);
5316 err_code |= ERR_ALERT | ERR_FATAL;
5317 goto out;
5318 } else {
5319 struct tcpcheck_rule *tcpcheck;
5320
5321 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5322
5323 tcpcheck->action = TCPCHK_ACT_SEND;
5324 tcpcheck->string_len = strlen(args[2]);
5325 tcpcheck->string = strdup(args[2]);
5326 tcpcheck->expect_regex = NULL;
5327
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005328 /* comment for this tcpcheck line */
5329 if (strcmp(args[3], "comment") == 0) {
5330 if (!*args[4]) {
5331 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5332 file, linenum, args[3]);
5333 err_code |= ERR_ALERT | ERR_FATAL;
5334 goto out;
5335 }
5336 tcpcheck->comment = strdup(args[4]);
5337 }
5338
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005339 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5340 }
5341 }
5342 else if (strcmp(args[1], "send-binary") == 0) {
5343 if (! *(args[2]) ) {
5344 /* SEND binary string expected */
5345 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
5346 file, linenum, args[0], args[1], args[2]);
5347 err_code |= ERR_ALERT | ERR_FATAL;
5348 goto out;
5349 } else {
5350 struct tcpcheck_rule *tcpcheck;
5351 char *err = NULL;
5352
5353 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5354
5355 tcpcheck->action = TCPCHK_ACT_SEND;
5356 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5357 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5358 file, linenum, args[0], args[1], args[2], err);
5359 err_code |= ERR_ALERT | ERR_FATAL;
5360 goto out;
5361 }
5362 tcpcheck->expect_regex = NULL;
5363
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005364 /* comment for this tcpcheck line */
5365 if (strcmp(args[3], "comment") == 0) {
5366 if (!*args[4]) {
5367 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5368 file, linenum, args[3]);
5369 err_code |= ERR_ALERT | ERR_FATAL;
5370 goto out;
5371 }
5372 tcpcheck->comment = strdup(args[4]);
5373 }
5374
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005375 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5376 }
5377 }
5378 else if (strcmp(args[1], "expect") == 0) {
5379 const char *ptr_arg;
5380 int cur_arg;
5381 int inverse = 0;
5382
5383 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5384 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5385 err_code |= ERR_ALERT | ERR_FATAL;
5386 goto out;
5387 }
5388
5389 cur_arg = 2;
5390 /* consider exclamation marks, sole or at the beginning of a word */
5391 while (*(ptr_arg = args[cur_arg])) {
5392 while (*ptr_arg == '!') {
5393 inverse = !inverse;
5394 ptr_arg++;
5395 }
5396 if (*ptr_arg)
5397 break;
5398 cur_arg++;
5399 }
5400 /* now ptr_arg points to the beginning of a word past any possible
5401 * exclamation mark, and cur_arg is the argument which holds this word.
5402 */
5403 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005404 struct tcpcheck_rule *tcpcheck;
5405 char *err = NULL;
5406
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005407 if (!*(args[cur_arg + 1])) {
5408 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
5409 file, linenum, args[0], args[1], ptr_arg);
5410 err_code |= ERR_ALERT | ERR_FATAL;
5411 goto out;
5412 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005413
5414 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5415
5416 tcpcheck->action = TCPCHK_ACT_EXPECT;
5417 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5418 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5419 file, linenum, args[0], args[1], args[2], err);
5420 err_code |= ERR_ALERT | ERR_FATAL;
5421 goto out;
5422 }
5423 tcpcheck->expect_regex = NULL;
5424 tcpcheck->inverse = inverse;
5425
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005426 /* tcpcheck comment */
5427 cur_arg += 2;
5428 if (strcmp(args[cur_arg], "comment") == 0) {
5429 if (!*args[cur_arg + 1]) {
5430 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5431 file, linenum, args[cur_arg + 1]);
5432 err_code |= ERR_ALERT | ERR_FATAL;
5433 goto out;
5434 }
5435 tcpcheck->comment = strdup(args[cur_arg + 1]);
5436 }
5437
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005438 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5439 }
5440 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005441 struct tcpcheck_rule *tcpcheck;
5442
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005443 if (!*(args[cur_arg + 1])) {
5444 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5445 file, linenum, args[0], args[1], ptr_arg);
5446 err_code |= ERR_ALERT | ERR_FATAL;
5447 goto out;
5448 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005449
5450 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5451
5452 tcpcheck->action = TCPCHK_ACT_EXPECT;
5453 tcpcheck->string_len = strlen(args[cur_arg + 1]);
5454 tcpcheck->string = strdup(args[cur_arg + 1]);
5455 tcpcheck->expect_regex = NULL;
5456 tcpcheck->inverse = inverse;
5457
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005458 /* tcpcheck comment */
5459 cur_arg += 2;
5460 if (strcmp(args[cur_arg], "comment") == 0) {
5461 if (!*args[cur_arg + 1]) {
5462 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5463 file, linenum, args[cur_arg + 1]);
5464 err_code |= ERR_ALERT | ERR_FATAL;
5465 goto out;
5466 }
5467 tcpcheck->comment = strdup(args[cur_arg + 1]);
5468 }
5469
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005470 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5471 }
5472 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005473 struct tcpcheck_rule *tcpcheck;
5474
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005475 if (!*(args[cur_arg + 1])) {
5476 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5477 file, linenum, args[0], args[1], ptr_arg);
5478 err_code |= ERR_ALERT | ERR_FATAL;
5479 goto out;
5480 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005481
5482 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5483
5484 tcpcheck->action = TCPCHK_ACT_EXPECT;
5485 tcpcheck->string_len = 0;
5486 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005487 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
5488 error = NULL;
5489 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
5490 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5491 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5492 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005493 err_code |= ERR_ALERT | ERR_FATAL;
5494 goto out;
5495 }
5496 tcpcheck->inverse = inverse;
5497
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005498 /* tcpcheck comment */
5499 cur_arg += 2;
5500 if (strcmp(args[cur_arg], "comment") == 0) {
5501 if (!*args[cur_arg + 1]) {
5502 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5503 file, linenum, args[cur_arg + 1]);
5504 err_code |= ERR_ALERT | ERR_FATAL;
5505 goto out;
5506 }
5507 tcpcheck->comment = strdup(args[cur_arg + 1]);
5508 }
5509
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005510 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5511 }
5512 else {
5513 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
5514 file, linenum, args[0], args[1], ptr_arg);
5515 err_code |= ERR_ALERT | ERR_FATAL;
5516 goto out;
5517 }
5518 }
5519 else {
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005520 Alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005521 err_code |= ERR_ALERT | ERR_FATAL;
5522 goto out;
5523 }
5524 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01005525 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02005526 if (curproxy == &defproxy) {
5527 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005528 err_code |= ERR_ALERT | ERR_FATAL;
5529 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02005530 }
5531
Willy Tarreaub80c2302007-11-30 20:51:32 +01005532 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005533 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005534
5535 if (strcmp(args[1], "fail") == 0) {
5536 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01005537 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01005538 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
5539 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005540 err_code |= ERR_ALERT | ERR_FATAL;
5541 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005542 }
5543
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005544 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
5545 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
5546 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005547 err_code |= ERR_ALERT | ERR_FATAL;
5548 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005549 }
5550 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
5551 }
5552 else {
5553 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005554 err_code |= ERR_ALERT | ERR_FATAL;
5555 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005556 }
5557 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005558#ifdef TPROXY
5559 else if (!strcmp(args[0], "transparent")) {
5560 /* enable transparent proxy connections */
5561 curproxy->options |= PR_O_TRANSP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005562 if (alertif_too_many_args(0, file, linenum, args, &err_code))
5563 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005564 }
5565#endif
5566 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005567 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005568 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005569
Willy Tarreaubaaee002006-06-26 02:48:02 +02005570 if (*(args[1]) == 0) {
5571 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005572 err_code |= ERR_ALERT | ERR_FATAL;
5573 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005574 }
5575 curproxy->maxconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005576 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5577 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005578 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005579 else if (!strcmp(args[0], "backlog")) { /* backlog */
5580 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005581 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005582
5583 if (*(args[1]) == 0) {
5584 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005585 err_code |= ERR_ALERT | ERR_FATAL;
5586 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005587 }
5588 curproxy->backlog = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005589 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5590 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005591 }
Willy Tarreau86034312006-12-29 00:10:33 +01005592 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005593 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005594 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005595
Willy Tarreau86034312006-12-29 00:10:33 +01005596 if (*(args[1]) == 0) {
5597 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005598 err_code |= ERR_ALERT | ERR_FATAL;
5599 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005600 }
5601 curproxy->fullconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005602 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5603 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005604 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005605 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
5606 if (*(args[1]) == 0) {
5607 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005608 err_code |= ERR_ALERT | ERR_FATAL;
5609 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005610 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005611 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
5612 if (err) {
5613 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
5614 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02005615 err_code |= ERR_ALERT | ERR_FATAL;
5616 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005617 }
5618 curproxy->grace = val;
William Lallemanddf1425a2015-04-28 20:17:49 +02005619 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5620 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005621 }
5622 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01005623 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005624 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005625 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005626
Willy Tarreaubaaee002006-06-26 02:48:02 +02005627 if (curproxy == &defproxy) {
5628 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005629 err_code |= ERR_ALERT | ERR_FATAL;
5630 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005631 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005632 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005633 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005634
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02005635 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005636 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005637 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005638 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005639 goto out;
5640 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005641
5642 proto = protocol_by_family(sk->ss_family);
5643 if (!proto || !proto->connect) {
5644 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5645 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005646 err_code |= ERR_ALERT | ERR_FATAL;
5647 goto out;
5648 }
5649
5650 if (port1 != port2) {
5651 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5652 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005653 err_code |= ERR_ALERT | ERR_FATAL;
5654 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005655 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005656
5657 if (!port1) {
5658 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5659 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005660 err_code |= ERR_ALERT | ERR_FATAL;
5661 goto out;
5662 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005663
William Lallemanddf1425a2015-04-28 20:17:49 +02005664 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5665 goto out;
5666
Willy Tarreaud5191e72010-02-09 20:50:45 +01005667 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005668 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005669 }
5670 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005671 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005672 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005673
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005674 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5675 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005676 err_code |= ERR_ALERT | ERR_FATAL;
5677 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005678 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005679 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005680 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005681 /**
5682 * The syntax for hash-type config element is
5683 * hash-type {map-based|consistent} [[<algo>] avalanche]
5684 *
5685 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5686 */
5687 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005688
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005689 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5690 err_code |= ERR_WARN;
5691
5692 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005693 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5694 }
5695 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005696 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5697 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005698 else if (strcmp(args[1], "avalanche") == 0) {
5699 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]);
5700 err_code |= ERR_ALERT | ERR_FATAL;
5701 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005702 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005703 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005704 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005705 err_code |= ERR_ALERT | ERR_FATAL;
5706 goto out;
5707 }
Bhaskar98634f02013-10-29 23:30:51 -04005708
5709 /* set the hash function to use */
5710 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005711 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005712 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005713
5714 /* if consistent with no argument, then avalanche modifier is also applied */
5715 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5716 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005717 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005718 /* set the hash function */
5719 if (!strcmp(args[2], "sdbm")) {
5720 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5721 }
5722 else if (!strcmp(args[2], "djb2")) {
5723 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005724 }
5725 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005726 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005727 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005728 else if (!strcmp(args[2], "crc32")) {
5729 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5730 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005731 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005732 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 -05005733 err_code |= ERR_ALERT | ERR_FATAL;
5734 goto out;
5735 }
5736
5737 /* set the hash modifier */
5738 if (!strcmp(args[3], "avalanche")) {
5739 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5740 }
5741 else if (*args[3]) {
5742 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5743 err_code |= ERR_ALERT | ERR_FATAL;
5744 goto out;
5745 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005746 }
William Lallemanda73203e2012-03-12 12:48:57 +01005747 }
William Lallemanda73203e2012-03-12 12:48:57 +01005748 else if (strcmp(args[0], "unique-id-format") == 0) {
5749 if (!*(args[1])) {
5750 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5751 err_code |= ERR_ALERT | ERR_FATAL;
5752 goto out;
5753 }
William Lallemand3203ff42012-11-11 17:30:56 +01005754 if (*(args[2])) {
5755 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5756 err_code |= ERR_ALERT | ERR_FATAL;
5757 goto out;
5758 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005759 free(curproxy->conf.uniqueid_format_string);
5760 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005761
Willy Tarreau62a61232013-04-12 18:13:46 +02005762 free(curproxy->conf.uif_file);
5763 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5764 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005765 }
William Lallemanda73203e2012-03-12 12:48:57 +01005766
5767 else if (strcmp(args[0], "unique-id-header") == 0) {
5768 if (!*(args[1])) {
5769 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5770 err_code |= ERR_ALERT | ERR_FATAL;
5771 goto out;
5772 }
5773 free(curproxy->header_unique_id);
5774 curproxy->header_unique_id = strdup(args[1]);
5775 }
5776
William Lallemand723b73a2012-02-08 16:37:49 +01005777 else if (strcmp(args[0], "log-format") == 0) {
5778 if (!*(args[1])) {
5779 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5780 err_code |= ERR_ALERT | ERR_FATAL;
5781 goto out;
5782 }
William Lallemand3203ff42012-11-11 17:30:56 +01005783 if (*(args[2])) {
5784 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5785 err_code |= ERR_ALERT | ERR_FATAL;
5786 goto out;
5787 }
Willy Tarreau196729e2012-05-31 19:30:26 +02005788
Willy Tarreau62a61232013-04-12 18:13:46 +02005789 if (curproxy->conf.logformat_string != default_http_log_format &&
5790 curproxy->conf.logformat_string != default_tcp_log_format &&
5791 curproxy->conf.logformat_string != clf_http_log_format)
5792 free(curproxy->conf.logformat_string);
5793 curproxy->conf.logformat_string = strdup(args[1]);
5794
5795 free(curproxy->conf.lfs_file);
5796 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5797 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005798
5799 /* get a chance to improve log-format error reporting by
5800 * reporting the correct line-number when possible.
5801 */
5802 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5803 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5804 file, linenum, curproxy->id);
5805 err_code |= ERR_WARN;
5806 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005807 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01005808 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
5809 if (*(args[1]) == 0) {
5810 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
5811 err_code |= ERR_ALERT | ERR_FATAL;
5812 goto out;
5813 }
5814 free(curproxy->log_tag);
5815 curproxy->log_tag = strdup(args[1]);
5816 }
William Lallemand0f99e342011-10-12 17:50:54 +02005817 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
5818 /* delete previous herited or defined syslog servers */
5819 struct logsrv *back;
5820
5821 if (*(args[1]) != 0) {
5822 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
5823 err_code |= ERR_ALERT | ERR_FATAL;
5824 goto out;
5825 }
5826
William Lallemand723b73a2012-02-08 16:37:49 +01005827 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
5828 LIST_DEL(&tmplogsrv->list);
5829 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02005830 }
5831 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005832 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02005833 struct logsrv *logsrv;
5834
Willy Tarreaubaaee002006-06-26 02:48:02 +02005835 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005836 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01005837 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02005838 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01005839 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02005840 LIST_INIT(&node->list);
5841 LIST_ADDQ(&curproxy->logsrvs, &node->list);
5842 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005843 }
5844 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005845 struct sockaddr_storage *sk;
5846 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02005847 int arg = 0;
5848 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02005849
5850 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005851
Willy Tarreau18324f52014-06-27 18:10:07 +02005852 /* just after the address, a length may be specified */
5853 if (strcmp(args[arg+2], "len") == 0) {
5854 len = atoi(args[arg+3]);
5855 if (len < 80 || len > 65535) {
5856 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
5857 file, linenum, args[arg+3]);
5858 err_code |= ERR_ALERT | ERR_FATAL;
5859 goto out;
5860 }
5861 logsrv->maxlen = len;
5862
5863 /* skip these two args */
5864 arg += 2;
5865 }
5866 else
5867 logsrv->maxlen = MAX_SYSLOG_LEN;
5868
5869 if (logsrv->maxlen > global.max_syslog_len) {
5870 global.max_syslog_len = logsrv->maxlen;
Dragan Dosen59cee972015-09-19 22:09:02 +02005871 logheader = realloc(logheader, global.max_syslog_len + 1);
Dragan Dosen1322d092015-09-22 16:05:32 +02005872 logheader_rfc5424 = realloc(logheader_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02005873 logline = realloc(logline, global.max_syslog_len + 1);
5874 }
5875
Dragan Dosen1322d092015-09-22 16:05:32 +02005876 /* after the length, a format may be specified */
5877 if (strcmp(args[arg+2], "format") == 0) {
5878 logsrv->format = get_log_format(args[arg+3]);
5879 if (logsrv->format < 0) {
5880 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
5881 err_code |= ERR_ALERT | ERR_FATAL;
5882 goto out;
5883 }
5884
5885 /* skip these two args */
5886 arg += 2;
5887 }
5888
William Lallemanddf1425a2015-04-28 20:17:49 +02005889 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
5890 goto out;
5891
Willy Tarreau18324f52014-06-27 18:10:07 +02005892 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005893 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005894 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005895 err_code |= ERR_ALERT | ERR_FATAL;
5896 goto out;
5897
Willy Tarreaubaaee002006-06-26 02:48:02 +02005898 }
5899
William Lallemand0f99e342011-10-12 17:50:54 +02005900 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02005901 if (*(args[arg+3])) {
5902 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005903 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005904 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005905 err_code |= ERR_ALERT | ERR_FATAL;
5906 goto out;
5907
Willy Tarreaubaaee002006-06-26 02:48:02 +02005908 }
5909 }
5910
William Lallemand0f99e342011-10-12 17:50:54 +02005911 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02005912 if (*(args[arg+4])) {
5913 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01005914 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005915 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02005916 err_code |= ERR_ALERT | ERR_FATAL;
5917 goto out;
5918
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005919 }
5920 }
5921
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02005922 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005923 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005924 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005925 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005926 goto out;
5927 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005928
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005929 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005930
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005931 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005932 if (port1 != port2) {
5933 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5934 file, linenum, args[0], args[1]);
5935 err_code |= ERR_ALERT | ERR_FATAL;
5936 goto out;
5937 }
5938
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005939 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02005940 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005941 }
William Lallemand0f99e342011-10-12 17:50:54 +02005942
5943 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005944 }
5945 else {
5946 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
5947 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005948 err_code |= ERR_ALERT | ERR_FATAL;
5949 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005950 }
5951 }
5952 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005953 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005954 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01005955 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005956 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005957
Willy Tarreau977b8e42006-12-29 14:19:17 +01005958 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005959 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005960
Willy Tarreaubaaee002006-06-26 02:48:02 +02005961 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005962 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
5963 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005964 err_code |= ERR_ALERT | ERR_FATAL;
5965 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005966 }
Willy Tarreau368480c2009-03-01 08:27:21 +01005967
5968 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01005969 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5970 free(curproxy->conn_src.iface_name);
5971 curproxy->conn_src.iface_name = NULL;
5972 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01005973
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02005974 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005975 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005976 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005977 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005978 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005979 goto out;
5980 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005981
5982 proto = protocol_by_family(sk->ss_family);
5983 if (!proto || !proto->connect) {
5984 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005985 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005986 err_code |= ERR_ALERT | ERR_FATAL;
5987 goto out;
5988 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005989
5990 if (port1 != port2) {
5991 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5992 file, linenum, args[0], args[1]);
5993 err_code |= ERR_ALERT | ERR_FATAL;
5994 goto out;
5995 }
5996
Willy Tarreauef9a3602012-12-08 22:29:20 +01005997 curproxy->conn_src.source_addr = *sk;
5998 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005999
6000 cur_arg = 2;
6001 while (*(args[cur_arg])) {
6002 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau29fbe512015-08-20 19:35:14 +02006003#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006004 if (!*args[cur_arg + 1]) {
6005 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
6006 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006007 err_code |= ERR_ALERT | ERR_FATAL;
6008 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006009 }
6010
6011 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006012 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6013 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006014 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006015 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6016 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02006017 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
6018 char *name, *end;
6019
6020 name = args[cur_arg+1] + 7;
6021 while (isspace(*name))
6022 name++;
6023
6024 end = name;
6025 while (*end && !isspace(*end) && *end != ',' && *end != ')')
6026 end++;
6027
Willy Tarreauef9a3602012-12-08 22:29:20 +01006028 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6029 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
6030 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
6031 curproxy->conn_src.bind_hdr_len = end - name;
6032 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
6033 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
6034 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02006035
6036 /* now look for an occurrence number */
6037 while (isspace(*end))
6038 end++;
6039 if (*end == ',') {
6040 end++;
6041 name = end;
6042 if (*end == '-')
6043 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01006044 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02006045 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01006046 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006047 }
6048
Willy Tarreauef9a3602012-12-08 22:29:20 +01006049 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02006050 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
6051 " occurrences values smaller than %d.\n",
6052 file, linenum, MAX_HDR_HISTORY);
6053 err_code |= ERR_ALERT | ERR_FATAL;
6054 goto out;
6055 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006056 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01006057 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006058
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006059 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006060 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006061 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006062 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006063 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006064 goto out;
6065 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006066
6067 proto = protocol_by_family(sk->ss_family);
6068 if (!proto || !proto->connect) {
6069 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
6070 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006071 err_code |= ERR_ALERT | ERR_FATAL;
6072 goto out;
6073 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006074
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006075 if (port1 != port2) {
6076 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6077 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006078 err_code |= ERR_ALERT | ERR_FATAL;
6079 goto out;
6080 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006081 curproxy->conn_src.tproxy_addr = *sk;
6082 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006083 }
6084 global.last_checks |= LSTCHK_NETADM;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006085#else /* no TPROXY support */
6086 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01006087 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006088 err_code |= ERR_ALERT | ERR_FATAL;
6089 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006090#endif
6091 cur_arg += 2;
6092 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01006093 }
6094
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006095 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
6096#ifdef SO_BINDTODEVICE
6097 if (!*args[cur_arg + 1]) {
6098 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
6099 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006100 err_code |= ERR_ALERT | ERR_FATAL;
6101 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006102 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006103 free(curproxy->conn_src.iface_name);
6104 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
6105 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006106 global.last_checks |= LSTCHK_NETADM;
6107#else
6108 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
6109 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02006110 err_code |= ERR_ALERT | ERR_FATAL;
6111 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01006112#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006113 cur_arg += 2;
6114 continue;
6115 }
6116 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02006117 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006118 err_code |= ERR_ALERT | ERR_FATAL;
6119 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006120 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006121 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006122 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
6123 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
6124 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02006125 err_code |= ERR_ALERT | ERR_FATAL;
6126 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006127 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006128 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006129 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006130 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6131 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006132 err_code |= ERR_ALERT | ERR_FATAL;
6133 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006134 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006135
6136 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006137 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006138 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006139 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006140 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006141 }
6142 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006143 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006144 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006145 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006146 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006147 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006148 }
6149 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006150 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006151 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006152 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006153 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006154 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006155 }
6156 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006157 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006158 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006159 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006160 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006161 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006162 }
6163 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006164 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006165 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006166 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006167 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006168 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006169 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006170 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006171 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006172 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006173 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006174 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006175 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006176 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006177 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006178 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006179 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6180 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006181 err_code |= ERR_ALERT | ERR_FATAL;
6182 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006183 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006184
6185 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006186 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006187 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006188 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006189 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006190 }
6191 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006192 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006193 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006194 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006195 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006196 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006197 }
6198 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006199 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006200 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006201 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006202 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006203 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006204 }
6205 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006206 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006207 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006208 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006209 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006210 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006211 }
6212 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006213 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006214 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006215 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006216 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006217 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006218 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006219 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006220 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006221 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006222 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006223 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006224 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006225 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006226 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006227 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006228
Willy Tarreaubaaee002006-06-26 02:48:02 +02006229 if (curproxy == &defproxy) {
6230 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006231 err_code |= ERR_ALERT | ERR_FATAL;
6232 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006233 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006234 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006235 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006236
Willy Tarreaubaaee002006-06-26 02:48:02 +02006237 if (*(args[1]) == 0) {
6238 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006239 err_code |= ERR_ALERT | ERR_FATAL;
6240 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006241 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006242
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006243 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006244 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6245 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6246 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006247 err_code |= ERR_ALERT | ERR_FATAL;
6248 goto out;
6249 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006250 err_code |= warnif_cond_conflicts(cond,
6251 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6252 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006253 }
6254 else if (*args[2]) {
6255 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6256 file, linenum, args[0], args[2]);
6257 err_code |= ERR_ALERT | ERR_FATAL;
6258 goto out;
6259 }
6260
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006261 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006262 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006263 wl->s = strdup(args[1]);
6264 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02006265 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006266 }
6267 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006268 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006269 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6270 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006271 err_code |= ERR_ALERT | ERR_FATAL;
6272 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006273 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006274
Willy Tarreauade5ec42010-01-28 19:33:49 +01006275 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006276 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006277 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006278 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006279 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006280 }
6281 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006282 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006283 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006284 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006285 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006286 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006287 }
6288 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006289 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006290 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006291 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006292 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006293 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006294 }
6295 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006296 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006297 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6298 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006299 err_code |= ERR_ALERT | ERR_FATAL;
6300 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006301 }
6302
Willy Tarreauade5ec42010-01-28 19:33:49 +01006303 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006304 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006305 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006306 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006307 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006308 }
6309 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006310 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006311 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006312 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006313 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006314 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006315 }
6316 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006317 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006318 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006319 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006320 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006321 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006322 }
6323 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006324 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006325
Willy Tarreaubaaee002006-06-26 02:48:02 +02006326 if (curproxy == &defproxy) {
6327 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006328 err_code |= ERR_ALERT | ERR_FATAL;
6329 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006330 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006331 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006332 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006333
Willy Tarreaubaaee002006-06-26 02:48:02 +02006334 if (*(args[1]) == 0) {
6335 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006336 err_code |= ERR_ALERT | ERR_FATAL;
6337 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006338 }
6339
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006340 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006341 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6342 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6343 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006344 err_code |= ERR_ALERT | ERR_FATAL;
6345 goto out;
6346 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006347 err_code |= warnif_cond_conflicts(cond,
6348 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
6349 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006350 }
6351 else if (*args[2]) {
6352 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6353 file, linenum, args[0], args[2]);
6354 err_code |= ERR_ALERT | ERR_FATAL;
6355 goto out;
6356 }
6357
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006358 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006359 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006360 wl->s = strdup(args[1]);
6361 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006362 }
6363 else if (!strcmp(args[0], "errorloc") ||
6364 !strcmp(args[0], "errorloc302") ||
6365 !strcmp(args[0], "errorloc303")) { /* error location */
6366 int errnum, errlen;
6367 char *err;
6368
Willy Tarreau977b8e42006-12-29 14:19:17 +01006369 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006370 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006371
Willy Tarreaubaaee002006-06-26 02:48:02 +02006372 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006373 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006374 err_code |= ERR_ALERT | ERR_FATAL;
6375 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006376 }
6377
6378 errnum = atol(args[1]);
6379 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006380 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
6381 err = malloc(errlen);
6382 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006383 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006384 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
6385 err = malloc(errlen);
6386 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006387 }
6388
Willy Tarreau0f772532006-12-23 20:51:41 +01006389 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6390 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006391 chunk_destroy(&curproxy->errmsg[rc]);
6392 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01006393 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006394 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006395 }
Willy Tarreau0f772532006-12-23 20:51:41 +01006396
6397 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006398 Warning("parsing [%s:%d] : status code %d not handled by '%s', error relocation will be ignored.\n",
6399 file, linenum, errnum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006400 free(err);
6401 }
6402 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02006403 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
6404 int errnum, errlen, fd;
6405 char *err;
6406 struct stat stat;
6407
6408 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006409 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006410
6411 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006412 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006413 err_code |= ERR_ALERT | ERR_FATAL;
6414 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006415 }
6416
6417 fd = open(args[2], O_RDONLY);
6418 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
6419 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
6420 file, linenum, args[2], args[1]);
6421 if (fd >= 0)
6422 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02006423 err_code |= ERR_ALERT | ERR_FATAL;
6424 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006425 }
6426
Willy Tarreau27a674e2009-08-17 07:23:33 +02006427 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02006428 errlen = stat.st_size;
6429 } else {
6430 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02006431 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02006432 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02006433 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006434 }
6435
6436 err = malloc(errlen); /* malloc() must succeed during parsing */
6437 errnum = read(fd, err, errlen);
6438 if (errnum != errlen) {
6439 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
6440 file, linenum, args[2], args[1]);
6441 close(fd);
6442 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02006443 err_code |= ERR_ALERT | ERR_FATAL;
6444 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006445 }
6446 close(fd);
6447
6448 errnum = atol(args[1]);
6449 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6450 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006451 chunk_destroy(&curproxy->errmsg[rc]);
6452 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02006453 break;
6454 }
6455 }
6456
6457 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006458 Warning("parsing [%s:%d] : status code %d not handled by '%s', error customization will be ignored.\n",
6459 file, linenum, errnum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006460 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006461 free(err);
6462 }
6463 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006464 else if (!strcmp(args[0], "compression")) {
6465 struct comp *comp;
6466 if (curproxy->comp == NULL) {
6467 comp = calloc(1, sizeof(struct comp));
6468 curproxy->comp = comp;
6469 } else {
6470 comp = curproxy->comp;
6471 }
6472
6473 if (!strcmp(args[1], "algo")) {
6474 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01006475 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01006476
William Lallemand82fe75c2012-10-23 10:25:10 +02006477 cur_arg = 2;
6478 if (!*args[cur_arg]) {
6479 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
6480 file, linenum, args[0]);
6481 err_code |= ERR_ALERT | ERR_FATAL;
6482 goto out;
6483 }
6484 while (*(args[cur_arg])) {
6485 if (comp_append_algo(comp, args[cur_arg]) < 0) {
6486 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
6487 file, linenum, args[0], args[cur_arg]);
6488 err_code |= ERR_ALERT | ERR_FATAL;
6489 goto out;
6490 }
William Lallemand552df672012-11-07 13:21:47 +01006491 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
6492 curproxy->comp->algos->end(&ctx);
6493 } else {
6494 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
6495 file, linenum, args[0], args[cur_arg]);
6496 err_code |= ERR_ALERT | ERR_FATAL;
6497 goto out;
6498 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006499 cur_arg ++;
6500 continue;
6501 }
6502 }
Willy Tarreau70737d12012-10-27 00:34:28 +02006503 else if (!strcmp(args[1], "offload")) {
6504 comp->offload = 1;
6505 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006506 else if (!strcmp(args[1], "type")) {
6507 int cur_arg;
6508 cur_arg = 2;
6509 if (!*args[cur_arg]) {
6510 Alert("parsing [%s:%d] : '%s' expects <type>\n",
6511 file, linenum, args[0]);
6512 err_code |= ERR_ALERT | ERR_FATAL;
6513 goto out;
6514 }
6515 while (*(args[cur_arg])) {
6516 comp_append_type(comp, args[cur_arg]);
6517 cur_arg ++;
6518 continue;
6519 }
6520 }
6521 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02006522 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02006523 file, linenum, args[0]);
6524 err_code |= ERR_ALERT | ERR_FATAL;
6525 goto out;
6526 }
6527 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006528 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006529 struct cfg_kw_list *kwl;
6530 int index;
6531
6532 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6533 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6534 if (kwl->kw[index].section != CFG_LISTEN)
6535 continue;
6536 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6537 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006538 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006539 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006540 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006541 err_code |= ERR_ALERT | ERR_FATAL;
6542 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006543 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006544 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006545 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006546 err_code |= ERR_WARN;
6547 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006548 }
Willy Tarreau93893792009-07-23 13:19:11 +02006549 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006550 }
6551 }
6552 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006553
Willy Tarreau6daf3432008-01-22 16:44:08 +01006554 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006555 err_code |= ERR_ALERT | ERR_FATAL;
6556 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006557 }
Willy Tarreau93893792009-07-23 13:19:11 +02006558 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006559 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006560 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006561}
6562
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006563int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006564cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
6565{
6566#ifdef CONFIG_HAP_NS
6567 const char *err;
6568 const char *item = args[0];
6569
6570 if (!strcmp(item, "namespace_list")) {
6571 return 0;
6572 }
6573 else if (!strcmp(item, "namespace")) {
6574 size_t idx = 1;
6575 const char *current;
6576 while (*(current = args[idx++])) {
6577 err = invalid_char(current);
6578 if (err) {
6579 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6580 file, linenum, *err, item, current);
6581 return ERR_ALERT | ERR_FATAL;
6582 }
6583
6584 if (netns_store_lookup(current, strlen(current))) {
6585 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
6586 file, linenum, current);
6587 return ERR_ALERT | ERR_FATAL;
6588 }
6589 if (!netns_store_insert(current)) {
6590 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
6591 file, linenum, current);
6592 return ERR_ALERT | ERR_FATAL;
6593 }
6594 }
6595 }
6596
6597 return 0;
6598#else
6599 Alert("parsing [%s:%d]: namespace support is not compiled in.",
6600 file, linenum);
6601 return ERR_ALERT | ERR_FATAL;
6602#endif
6603}
6604
6605int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006606cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6607{
6608
6609 int err_code = 0;
6610 const char *err;
6611
6612 if (!strcmp(args[0], "userlist")) { /* new userlist */
6613 struct userlist *newul;
6614
6615 if (!*args[1]) {
6616 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6617 file, linenum, args[0]);
6618 err_code |= ERR_ALERT | ERR_FATAL;
6619 goto out;
6620 }
William Lallemand6e62fb62015-04-28 16:55:23 +02006621 if (alertif_too_many_args(1, file, linenum, args, &err_code))
6622 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006623
6624 err = invalid_char(args[1]);
6625 if (err) {
6626 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6627 file, linenum, *err, args[0], args[1]);
6628 err_code |= ERR_ALERT | ERR_FATAL;
6629 goto out;
6630 }
6631
6632 for (newul = userlist; newul; newul = newul->next)
6633 if (!strcmp(newul->name, args[1])) {
6634 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6635 file, linenum, args[1]);
6636 err_code |= ERR_WARN;
6637 goto out;
6638 }
6639
6640 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
6641 if (!newul) {
6642 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6643 err_code |= ERR_ALERT | ERR_ABORT;
6644 goto out;
6645 }
6646
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006647 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006648 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006649 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6650 err_code |= ERR_ALERT | ERR_ABORT;
6651 goto out;
6652 }
6653
6654 newul->next = userlist;
6655 userlist = newul;
6656
6657 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006658 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006659 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006660 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006661
6662 if (!*args[1]) {
6663 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6664 file, linenum, args[0]);
6665 err_code |= ERR_ALERT | ERR_FATAL;
6666 goto out;
6667 }
6668
6669 err = invalid_char(args[1]);
6670 if (err) {
6671 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6672 file, linenum, *err, args[0], args[1]);
6673 err_code |= ERR_ALERT | ERR_FATAL;
6674 goto out;
6675 }
6676
William Lallemand4ac9f542015-05-28 18:03:51 +02006677 if (!userlist)
6678 goto out;
6679
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006680 for (ag = userlist->groups; ag; ag = ag->next)
6681 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006682 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6683 file, linenum, args[1], userlist->name);
6684 err_code |= ERR_ALERT;
6685 goto out;
6686 }
6687
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006688 ag = calloc(1, sizeof(*ag));
6689 if (!ag) {
6690 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6691 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006692 goto out;
6693 }
6694
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006695 ag->name = strdup(args[1]);
6696 if (!ag) {
6697 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6698 err_code |= ERR_ALERT | ERR_ABORT;
6699 goto out;
6700 }
6701
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006702 cur_arg = 2;
6703
6704 while (*args[cur_arg]) {
6705 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006706 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006707 cur_arg += 2;
6708 continue;
6709 } else {
6710 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6711 file, linenum, args[0]);
6712 err_code |= ERR_ALERT | ERR_FATAL;
6713 goto out;
6714 }
6715 }
6716
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006717 ag->next = userlist->groups;
6718 userlist->groups = ag;
6719
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006720 } else if (!strcmp(args[0], "user")) { /* new user */
6721 struct auth_users *newuser;
6722 int cur_arg;
6723
6724 if (!*args[1]) {
6725 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6726 file, linenum, args[0]);
6727 err_code |= ERR_ALERT | ERR_FATAL;
6728 goto out;
6729 }
William Lallemand4ac9f542015-05-28 18:03:51 +02006730 if (!userlist)
6731 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006732
6733 for (newuser = userlist->users; newuser; newuser = newuser->next)
6734 if (!strcmp(newuser->user, args[1])) {
6735 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6736 file, linenum, args[1], userlist->name);
6737 err_code |= ERR_ALERT;
6738 goto out;
6739 }
6740
6741 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
6742 if (!newuser) {
6743 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6744 err_code |= ERR_ALERT | ERR_ABORT;
6745 goto out;
6746 }
6747
6748 newuser->user = strdup(args[1]);
6749
6750 newuser->next = userlist->users;
6751 userlist->users = newuser;
6752
6753 cur_arg = 2;
6754
6755 while (*args[cur_arg]) {
6756 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006757#ifdef CONFIG_HAP_CRYPT
6758 if (!crypt("", args[cur_arg + 1])) {
6759 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6760 file, linenum, newuser->user);
6761 err_code |= ERR_ALERT | ERR_FATAL;
6762 goto out;
6763 }
6764#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006765 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6766 file, linenum);
6767 err_code |= ERR_ALERT;
6768#endif
6769 newuser->pass = strdup(args[cur_arg + 1]);
6770 cur_arg += 2;
6771 continue;
6772 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6773 newuser->pass = strdup(args[cur_arg + 1]);
6774 newuser->flags |= AU_O_INSECURE;
6775 cur_arg += 2;
6776 continue;
6777 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006778 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006779 cur_arg += 2;
6780 continue;
6781 } else {
6782 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6783 file, linenum, args[0]);
6784 err_code |= ERR_ALERT | ERR_FATAL;
6785 goto out;
6786 }
6787 }
6788 } else {
6789 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6790 err_code |= ERR_ALERT | ERR_FATAL;
6791 }
6792
6793out:
6794 return err_code;
6795}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006796
6797/*
6798 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006799 * Returns the error code, 0 if OK, or any combination of :
6800 * - ERR_ABORT: must abort ASAP
6801 * - ERR_FATAL: we can continue parsing but not start the service
6802 * - ERR_WARN: a warning has been emitted
6803 * - ERR_ALERT: an alert has been emitted
6804 * Only the two first ones can stop processing, the two others are just
6805 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006806 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006807int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006808{
William Lallemand64e84512015-05-12 14:25:37 +02006809 char *thisline;
6810 int linesize = LINESIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006811 FILE *f;
6812 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02006813 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006814 struct cfg_section *cs = NULL;
6815 struct cfg_section *ics;
William Lallemand64e84512015-05-12 14:25:37 +02006816 int readbytes = 0;
6817
6818 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
William Lallemandb2f07452015-05-12 14:27:13 +02006819 Alert("parsing [%s] : out of memory.\n", file);
William Lallemand64e84512015-05-12 14:25:37 +02006820 return -1;
6821 }
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006822
6823 /* Register internal sections */
6824 if (!cfg_register_section("listen", cfg_parse_listen) ||
6825 !cfg_register_section("frontend", cfg_parse_listen) ||
6826 !cfg_register_section("backend", cfg_parse_listen) ||
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006827 !cfg_register_section("defaults", cfg_parse_listen) ||
6828 !cfg_register_section("global", cfg_parse_global) ||
6829 !cfg_register_section("userlist", cfg_parse_users) ||
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006830 !cfg_register_section("peers", cfg_parse_peers) ||
Simon Horman0d16a402015-01-30 11:22:58 +09006831 !cfg_register_section("mailers", cfg_parse_mailers) ||
Baptiste Assmann325137d2015-04-13 23:40:55 +02006832 !cfg_register_section("namespace_list", cfg_parse_netns) ||
6833 !cfg_register_section("resolvers", cfg_parse_resolvers))
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006834 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006835
Willy Tarreaubaaee002006-06-26 02:48:02 +02006836 if ((f=fopen(file,"r")) == NULL)
6837 return -1;
6838
William Lallemandb2f07452015-05-12 14:27:13 +02006839next_line:
William Lallemand64e84512015-05-12 14:25:37 +02006840 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02006841 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006842 char *end;
6843 char *args[MAX_LINE_ARGS + 1];
6844 char *line = thisline;
William Lallemandf9873ba2015-05-05 17:37:14 +02006845 int dquote = 0; /* double quote */
6846 int squote = 0; /* simple quote */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006847
Willy Tarreaubaaee002006-06-26 02:48:02 +02006848 linenum++;
6849
6850 end = line + strlen(line);
6851
William Lallemand64e84512015-05-12 14:25:37 +02006852 if (end-line == linesize-1 && *(end-1) != '\n') {
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006853 /* Check if we reached the limit and the last char is not \n.
6854 * Watch out for the last line without the terminating '\n'!
6855 */
William Lallemand64e84512015-05-12 14:25:37 +02006856 char *newline;
6857 int newlinesize = linesize * 2;
6858
6859 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
6860 if (newline == NULL) {
6861 Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
6862 file, linenum);
6863 err_code |= ERR_ALERT | ERR_FATAL;
6864 continue;
6865 }
6866
6867 readbytes = linesize - 1;
6868 linesize = newlinesize;
6869 thisline = newline;
6870 continue;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006871 }
6872
William Lallemand64e84512015-05-12 14:25:37 +02006873 readbytes = 0;
6874
Willy Tarreaubaaee002006-06-26 02:48:02 +02006875 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006876 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006877 line++;
William Lallemandf9873ba2015-05-05 17:37:14 +02006878
Willy Tarreaubaaee002006-06-26 02:48:02 +02006879 arg = 0;
6880 args[arg] = line;
6881
6882 while (*line && arg < MAX_LINE_ARGS) {
William Lallemandf9873ba2015-05-05 17:37:14 +02006883 if (*line == '"' && !squote) { /* double quote outside single quotes */
6884 if (dquote)
6885 dquote = 0;
6886 else
6887 dquote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02006888 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02006889 end--;
6890 }
6891 else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
6892 if (squote)
6893 squote = 0;
6894 else
6895 squote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02006896 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02006897 end--;
6898 }
6899 else if (*line == '\\' && !squote) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006900 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
6901 * C equivalent value. Other combinations left unchanged (eg: \1).
6902 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006903 int skip = 0;
6904 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
6905 *line = line[1];
6906 skip = 1;
6907 }
6908 else if (line[1] == 'r') {
6909 *line = '\r';
6910 skip = 1;
William Lallemandf9873ba2015-05-05 17:37:14 +02006911 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006912 else if (line[1] == 'n') {
6913 *line = '\n';
6914 skip = 1;
6915 }
6916 else if (line[1] == 't') {
6917 *line = '\t';
6918 skip = 1;
6919 }
6920 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01006921 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006922 unsigned char hex1, hex2;
6923 hex1 = toupper(line[2]) - '0';
6924 hex2 = toupper(line[3]) - '0';
6925 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
6926 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
6927 *line = (hex1<<4) + hex2;
6928 skip = 3;
6929 }
6930 else {
6931 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006932 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006933 }
William Lallemandf9873ba2015-05-05 17:37:14 +02006934 } else if (line[1] == '"') {
6935 *line = '"';
6936 skip = 1;
6937 } else if (line[1] == '\'') {
6938 *line = '\'';
6939 skip = 1;
William Lallemandb2f07452015-05-12 14:27:13 +02006940 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
6941 *line = '$';
6942 skip = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006943 }
6944 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01006945 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006946 end -= skip;
6947 }
6948 line++;
6949 }
William Lallemandf9873ba2015-05-05 17:37:14 +02006950 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006951 /* end of string, end of loop */
6952 *line = 0;
6953 break;
6954 }
William Lallemandf9873ba2015-05-05 17:37:14 +02006955 else if (!squote && !dquote && isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006956 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006957 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006958 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006959 line++;
6960 args[++arg] = line;
6961 }
William Lallemandb2f07452015-05-12 14:27:13 +02006962 else if (dquote && *line == '$') {
6963 /* environment variables are evaluated inside double quotes */
6964 char *var_beg;
6965 char *var_end;
6966 char save_char;
6967 char *value;
6968 int val_len;
6969 int newlinesize;
6970 int braces = 0;
6971
6972 var_beg = line + 1;
6973 var_end = var_beg;
6974
6975 if (*var_beg == '{') {
6976 var_beg++;
6977 var_end++;
6978 braces = 1;
6979 }
6980
6981 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
6982 Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
6983 err_code |= ERR_ALERT | ERR_FATAL;
6984 goto next_line; /* skip current line */
6985 }
6986
6987 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
6988 var_end++;
6989
6990 save_char = *var_end;
6991 *var_end = '\0';
6992 value = getenv(var_beg);
6993 *var_end = save_char;
6994 val_len = value ? strlen(value) : 0;
6995
6996 if (braces) {
6997 if (*var_end == '}') {
6998 var_end++;
6999 braces = 0;
7000 } else {
7001 Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
7002 err_code |= ERR_ALERT | ERR_FATAL;
7003 goto next_line; /* skip current line */
7004 }
7005 }
7006
7007 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
7008
7009 /* if not enough space in thisline */
7010 if (newlinesize > linesize) {
7011 char *newline;
7012
7013 newline = realloc(thisline, newlinesize * sizeof(*thisline));
7014 if (newline == NULL) {
7015 Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
7016 err_code |= ERR_ALERT | ERR_FATAL;
7017 goto next_line; /* slip current line */
7018 }
7019 /* recompute pointers if realloc returns a new pointer */
7020 if (newline != thisline) {
7021 int i;
7022 int diff;
7023
7024 for (i = 0; i <= arg; i++) {
7025 diff = args[i] - thisline;
7026 args[i] = newline + diff;
7027 }
7028
7029 diff = var_end - thisline;
7030 var_end = newline + diff;
7031 diff = end - thisline;
7032 end = newline + diff;
7033 diff = line - thisline;
7034 line = newline + diff;
7035 thisline = newline;
7036 }
7037 linesize = newlinesize;
7038 }
7039
7040 /* insert value inside the line */
7041 memmove(line + val_len, var_end, end - var_end + 1);
7042 memcpy(line, value, val_len);
7043 end += val_len - (var_end - line);
7044 line += val_len;
7045 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007046 else {
7047 line++;
7048 }
7049 }
William Lallemandb2f07452015-05-12 14:27:13 +02007050
William Lallemandf9873ba2015-05-05 17:37:14 +02007051 if (dquote) {
7052 Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
7053 err_code |= ERR_ALERT | ERR_FATAL;
7054 }
7055
7056 if (squote) {
7057 Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
7058 err_code |= ERR_ALERT | ERR_FATAL;
7059 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007060
7061 /* empty line */
7062 if (!**args)
7063 continue;
7064
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007065 if (*line) {
7066 /* we had to stop due to too many args.
7067 * Let's terminate the string, print the offending part then cut the
7068 * last arg.
7069 */
7070 while (*line && *line != '#' && *line != '\n' && *line != '\r')
7071 line++;
7072 *line = '\0';
7073
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01007074 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01007075 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007076 err_code |= ERR_ALERT | ERR_FATAL;
7077 args[arg] = line;
7078 }
7079
Willy Tarreau540abe42007-05-02 20:50:16 +02007080 /* zero out remaining args and ensure that at least one entry
7081 * is zeroed out.
7082 */
7083 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007084 args[arg] = line;
7085 }
7086
Willy Tarreau3842f002009-06-14 11:39:52 +02007087 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007088 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02007089 char *tmp;
7090
Willy Tarreau3842f002009-06-14 11:39:52 +02007091 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02007092 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007093 for (arg=0; *args[arg+1]; arg++)
7094 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02007095 *tmp = '\0'; // fix the next arg to \0
7096 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007097 }
Willy Tarreau3842f002009-06-14 11:39:52 +02007098 else if (!strcmp(args[0], "default")) {
7099 kwm = KWM_DEF;
7100 for (arg=0; *args[arg+1]; arg++)
7101 args[arg] = args[arg+1]; // shift args after inversion
7102 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007103
William Lallemand0f99e342011-10-12 17:50:54 +02007104 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
7105 strcmp(args[0], "log") != 0) {
7106 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02007107 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007108 }
7109
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007110 /* detect section start */
7111 list_for_each_entry(ics, &sections, list) {
7112 if (strcmp(args[0], ics->section_name) == 0) {
7113 cursection = ics->section_name;
7114 cs = ics;
7115 break;
7116 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007117 }
7118
Willy Tarreaubaaee002006-06-26 02:48:02 +02007119 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007120 if (cs)
7121 err_code |= cs->section_parser(file, linenum, args, kwm);
7122 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007123 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007124 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007125 }
Willy Tarreau058e9072009-07-20 09:30:05 +02007126
7127 if (err_code & ERR_ABORT)
7128 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007129 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01007130 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02007131 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007132 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02007133 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007134}
7135
Willy Tarreau64ab6072014-09-16 12:17:36 +02007136/* This function propagates processes from frontend <from> to backend <to> so
7137 * that it is always guaranteed that a backend pointed to by a frontend is
7138 * bound to all of its processes. After that, if the target is a "listen"
7139 * instance, the function recursively descends the target's own targets along
Willy Tarreau98d04852015-05-26 12:18:29 +02007140 * default_backend and use_backend rules. Since the bits are
Willy Tarreau64ab6072014-09-16 12:17:36 +02007141 * checked first to ensure that <to> is already bound to all processes of
7142 * <from>, there is no risk of looping and we ensure to follow the shortest
7143 * path to the destination.
7144 *
7145 * It is possible to set <to> to NULL for the first call so that the function
7146 * takes care of visiting the initial frontend in <from>.
7147 *
7148 * It is important to note that the function relies on the fact that all names
7149 * have already been resolved.
7150 */
7151void propagate_processes(struct proxy *from, struct proxy *to)
7152{
7153 struct switching_rule *rule;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007154
7155 if (to) {
7156 /* check whether we need to go down */
7157 if (from->bind_proc &&
7158 (from->bind_proc & to->bind_proc) == from->bind_proc)
7159 return;
7160
7161 if (!from->bind_proc && !to->bind_proc)
7162 return;
7163
7164 to->bind_proc = from->bind_proc ?
7165 (to->bind_proc | from->bind_proc) : 0;
7166
7167 /* now propagate down */
7168 from = to;
7169 }
7170
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01007171 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02007172 return;
7173
Willy Tarreauf6b70012014-12-18 14:00:43 +01007174 if (from->state == PR_STSTOPPED)
7175 return;
7176
Willy Tarreau64ab6072014-09-16 12:17:36 +02007177 /* default_backend */
7178 if (from->defbe.be)
7179 propagate_processes(from, from->defbe.be);
7180
7181 /* use_backend */
7182 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02007183 if (rule->dynamic)
7184 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007185 to = rule->be.backend;
7186 propagate_processes(from, to);
7187 }
Willy Tarreau64ab6072014-09-16 12:17:36 +02007188}
7189
Willy Tarreaubb925012009-07-23 13:36:36 +02007190/*
7191 * Returns the error code, 0 if OK, or any combination of :
7192 * - ERR_ABORT: must abort ASAP
7193 * - ERR_FATAL: we can continue parsing but not start the service
7194 * - ERR_WARN: a warning has been emitted
7195 * - ERR_ALERT: an alert has been emitted
7196 * Only the two first ones can stop processing, the two others are just
7197 * indicators.
7198 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007199int check_config_validity()
7200{
7201 int cfgerr = 0;
7202 struct proxy *curproxy = NULL;
7203 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02007204 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007205 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007206 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007207
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007208 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007209 /*
7210 * Now, check for the integrity of all that we have collected.
7211 */
7212
7213 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02007214 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007215
Willy Tarreau193b8c62012-11-22 00:17:38 +01007216 if (!global.tune.max_http_hdr)
7217 global.tune.max_http_hdr = MAX_HTTP_HDR;
7218
7219 if (!global.tune.cookie_len)
7220 global.tune.cookie_len = CAPTURE_LEN;
7221
7222 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
7223
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007224 /* Post initialisation of the users and groups lists. */
7225 err_code = userlist_postinit();
7226 if (err_code != ERR_NONE)
7227 goto out;
7228
Willy Tarreau55bc0f82009-03-15 14:51:53 +01007229 /* first, we will invert the proxy list order */
7230 curproxy = NULL;
7231 while (proxy) {
7232 struct proxy *next;
7233
7234 next = proxy->next;
7235 proxy->next = curproxy;
7236 curproxy = proxy;
7237 if (!next)
7238 break;
7239 proxy = next;
7240 }
7241
Willy Tarreau419ead82014-09-16 13:41:21 +02007242 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007243 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007244 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01007245 struct sticking_rule *mrule;
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007246 struct act_rule *trule;
7247 struct act_rule *hrqrule;
Dragan Dosen1322d092015-09-22 16:05:32 +02007248 struct logsrv *tmplogsrv;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007249 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01007250 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007251
Willy Tarreau050536d2012-10-04 08:47:34 +02007252 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007253 /* proxy ID not set, use automatic numbering with first
7254 * spare entry starting with next_pxid.
7255 */
7256 next_pxid = get_next_id(&used_proxy_id, next_pxid);
7257 curproxy->conf.id.key = curproxy->uuid = next_pxid;
7258 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007259 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007260 next_pxid++;
7261
Willy Tarreau55ea7572007-06-17 19:56:27 +02007262
Willy Tarreaubaaee002006-06-26 02:48:02 +02007263 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02007264 /* ensure we don't keep listeners uselessly bound */
7265 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02007266 free((void *)curproxy->table.peers.name);
7267 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007268 continue;
7269 }
7270
Willy Tarreau102df612014-05-07 23:56:38 +02007271 /* Check multi-process mode compatibility for the current proxy */
7272
7273 if (curproxy->bind_proc) {
7274 /* an explicit bind-process was specified, let's check how many
7275 * processes remain.
7276 */
David Carliere6c39412015-07-02 07:00:17 +00007277 nbproc = my_popcountl(curproxy->bind_proc);
Willy Tarreau102df612014-05-07 23:56:38 +02007278
7279 curproxy->bind_proc &= nbits(global.nbproc);
7280 if (!curproxy->bind_proc && nbproc == 1) {
7281 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);
7282 curproxy->bind_proc = 1;
7283 }
7284 else if (!curproxy->bind_proc && nbproc > 1) {
7285 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);
7286 curproxy->bind_proc = 0;
7287 }
7288 }
7289
Willy Tarreau3d209582014-05-09 17:06:11 +02007290 /* check and reduce the bind-proc of each listener */
7291 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7292 unsigned long mask;
7293
7294 if (!bind_conf->bind_proc)
7295 continue;
7296
7297 mask = nbits(global.nbproc);
7298 if (curproxy->bind_proc)
7299 mask &= curproxy->bind_proc;
7300 /* mask cannot be null here thanks to the previous checks */
7301
David Carliere6c39412015-07-02 07:00:17 +00007302 nbproc = my_popcountl(bind_conf->bind_proc);
Willy Tarreau3d209582014-05-09 17:06:11 +02007303 bind_conf->bind_proc &= mask;
7304
7305 if (!bind_conf->bind_proc && nbproc == 1) {
7306 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",
7307 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7308 bind_conf->bind_proc = mask & ~(mask - 1);
7309 }
7310 else if (!bind_conf->bind_proc && nbproc > 1) {
7311 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",
7312 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7313 bind_conf->bind_proc = 0;
7314 }
7315 }
7316
Willy Tarreauff01a212009-03-15 13:46:16 +01007317 switch (curproxy->mode) {
7318 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007319 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007320 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007321 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
7322 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007323 cfgerr++;
7324 }
7325
7326 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007327 Warning("config : servers will be ignored for %s '%s'.\n",
7328 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007329 break;
7330
7331 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007332 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007333 break;
7334
7335 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01007336 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01007337 break;
7338 }
7339
Willy Tarreauf3934b82015-08-11 11:36:45 +02007340 if ((curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->conf.listeners)) {
7341 Warning("config : %s '%s' has no 'bind' directive. Please declare it as a backend if this was intended.\n",
7342 proxy_type_str(curproxy), curproxy->id);
7343 err_code |= ERR_WARN;
7344 }
7345
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007346 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007347 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007348 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007349 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
7350 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007351 cfgerr++;
7352 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007353#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007354 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007355 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
7356 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007357 cfgerr++;
7358 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007359#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02007360 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007361 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
7362 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007363 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007364 }
7365 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02007366 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007367 /* If no LB algo is set in a backend, and we're not in
7368 * transparent mode, dispatch mode nor proxy mode, we
7369 * want to use balance roundrobin by default.
7370 */
7371 curproxy->lbprm.algo &= ~BE_LB_ALGO;
7372 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007373 }
7374 }
Willy Tarreau193cf932007-09-17 10:17:23 +02007375
Willy Tarreau1620ec32011-08-06 17:05:02 +02007376 if (curproxy->options & PR_O_DISPATCH)
7377 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
7378 else if (curproxy->options & PR_O_HTTP_PROXY)
7379 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
7380 else if (curproxy->options & PR_O_TRANSP)
7381 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01007382
Willy Tarreau1620ec32011-08-06 17:05:02 +02007383 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
7384 if (curproxy->options & PR_O_DISABLE404) {
7385 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7386 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
7387 err_code |= ERR_WARN;
7388 curproxy->options &= ~PR_O_DISABLE404;
7389 }
7390 if (curproxy->options2 & PR_O2_CHK_SNDST) {
7391 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7392 "send-state", proxy_type_str(curproxy), curproxy->id);
7393 err_code |= ERR_WARN;
7394 curproxy->options &= ~PR_O2_CHK_SNDST;
7395 }
Willy Tarreauef781042010-01-27 11:53:01 +01007396 }
7397
Simon Horman98637e52014-06-20 12:30:16 +09007398 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
7399 if (!global.external_check) {
7400 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
7401 curproxy->id, "option external-check");
7402 cfgerr++;
7403 }
7404 if (!curproxy->check_command) {
7405 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
7406 curproxy->id, "option external-check");
7407 cfgerr++;
7408 }
7409 }
7410
Simon Horman64e34162015-02-06 11:11:57 +09007411 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007412 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
7413 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Pieter Baauw8669e972015-08-17 00:45:05 +02007414 "'email-alert from', 'email-alert level' 'email-alert mailers', "
7415 "'email-alert myhostname', or 'email-alert to' "
7416 "requires each of 'email-alert from', 'email-alert mailers' and 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007417 "to be present).\n",
7418 proxy_type_str(curproxy), curproxy->id);
7419 err_code |= ERR_WARN;
7420 free_email_alert(curproxy);
7421 }
7422 if (!curproxy->email_alert.myhostname)
7423 curproxy->email_alert.myhostname = hostname;
Simon Horman9dc49962015-01-30 11:22:59 +09007424 }
7425
Simon Horman98637e52014-06-20 12:30:16 +09007426 if (curproxy->check_command) {
7427 int clear = 0;
7428 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7429 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7430 "external-check command", proxy_type_str(curproxy), curproxy->id);
7431 err_code |= ERR_WARN;
7432 clear = 1;
7433 }
7434 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
7435 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-command path' is not set.\n",
7436 curproxy->id, "external-check command");
7437 cfgerr++;
7438 }
7439 if (clear) {
7440 free(curproxy->check_command);
7441 curproxy->check_command = NULL;
7442 }
7443 }
7444
7445 if (curproxy->check_path) {
7446 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7447 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7448 "external-check path", proxy_type_str(curproxy), curproxy->id);
7449 err_code |= ERR_WARN;
7450 free(curproxy->check_path);
7451 curproxy->check_path = NULL;
7452 }
7453 }
7454
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007455 /* if a default backend was specified, let's find it */
7456 if (curproxy->defbe.name) {
7457 struct proxy *target;
7458
Willy Tarreauafb39922015-05-26 12:04:09 +02007459 target = proxy_be_by_name(curproxy->defbe.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007460 if (!target) {
7461 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
7462 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007463 cfgerr++;
7464 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007465 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
7466 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02007467 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007468 } else if (target->mode != curproxy->mode &&
7469 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7470
7471 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) as its default backend (see 'mode').\n",
7472 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7473 curproxy->conf.file, curproxy->conf.line,
7474 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7475 target->conf.file, target->conf.line);
7476 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007477 } else {
7478 free(curproxy->defbe.name);
7479 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01007480
7481 /* Emit a warning if this proxy also has some servers */
7482 if (curproxy->srv) {
7483 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
7484 curproxy->id);
7485 err_code |= ERR_WARN;
7486 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007487 }
7488 }
7489
Willy Tarreau55ea7572007-06-17 19:56:27 +02007490 /* find the target proxy for 'use_backend' rules */
7491 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007492 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007493 struct logformat_node *node;
7494 char *pxname;
7495
7496 /* Try to parse the string as a log format expression. If the result
7497 * of the parsing is only one entry containing a simple string, then
7498 * it's a standard string corresponding to a static rule, thus the
7499 * parsing is cancelled and be.name is restored to be resolved.
7500 */
7501 pxname = rule->be.name;
7502 LIST_INIT(&rule->be.expr);
7503 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
7504 curproxy->conf.args.file, curproxy->conf.args.line);
7505 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
7506
7507 if (!LIST_ISEMPTY(&rule->be.expr)) {
7508 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
7509 rule->dynamic = 1;
7510 free(pxname);
7511 continue;
7512 }
7513 /* simple string: free the expression and fall back to static rule */
7514 free(node->arg);
7515 free(node);
7516 }
7517
7518 rule->dynamic = 0;
7519 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007520
Willy Tarreauafb39922015-05-26 12:04:09 +02007521 target = proxy_be_by_name(rule->be.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007522 if (!target) {
7523 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
7524 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007525 cfgerr++;
7526 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007527 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
7528 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007529 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007530 } else if (target->mode != curproxy->mode &&
7531 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7532
7533 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) in a 'use_backend' rule (see 'mode').\n",
7534 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7535 curproxy->conf.file, curproxy->conf.line,
7536 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7537 target->conf.file, target->conf.line);
7538 cfgerr++;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007539 } else {
7540 free((void *)rule->be.name);
7541 rule->be.backend = target;
7542 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007543 }
7544
Willy Tarreau64ab6072014-09-16 12:17:36 +02007545 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007546 list_for_each_entry(srule, &curproxy->server_rules, list) {
7547 struct server *target = findserver(curproxy, srule->srv.name);
7548
7549 if (!target) {
7550 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7551 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7552 cfgerr++;
7553 continue;
7554 }
7555 free((void *)srule->srv.name);
7556 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007557 }
7558
Emeric Brunb982a3d2010-01-04 15:45:53 +01007559 /* find the target table for 'stick' rules */
7560 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7561 struct proxy *target;
7562
Emeric Brun1d33b292010-01-04 15:47:17 +01007563 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7564 if (mrule->flags & STK_IS_STORE)
7565 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7566
Emeric Brunb982a3d2010-01-04 15:45:53 +01007567 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007568 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007569 else
7570 target = curproxy;
7571
7572 if (!target) {
7573 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7574 curproxy->id, mrule->table.name);
7575 cfgerr++;
7576 }
7577 else if (target->table.size == 0) {
7578 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7579 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7580 cfgerr++;
7581 }
Willy Tarreau12785782012-04-27 21:37:17 +02007582 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7583 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007584 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7585 cfgerr++;
7586 }
7587 else {
7588 free((void *)mrule->table.name);
7589 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007590 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007591 }
7592 }
7593
7594 /* find the target table for 'store response' rules */
7595 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7596 struct proxy *target;
7597
Emeric Brun1d33b292010-01-04 15:47:17 +01007598 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7599
Emeric Brunb982a3d2010-01-04 15:45:53 +01007600 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007601 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007602 else
7603 target = curproxy;
7604
7605 if (!target) {
7606 Alert("Proxy '%s': unable to find store table '%s'.\n",
7607 curproxy->id, mrule->table.name);
7608 cfgerr++;
7609 }
7610 else if (target->table.size == 0) {
7611 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7612 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7613 cfgerr++;
7614 }
Willy Tarreau12785782012-04-27 21:37:17 +02007615 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7616 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007617 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7618 cfgerr++;
7619 }
7620 else {
7621 free((void *)mrule->table.name);
7622 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007623 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007624 }
7625 }
7626
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007627 /* find the target table for 'tcp-request' layer 4 rules */
7628 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
7629 struct proxy *target;
7630
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007631 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007632 continue;
7633
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007634 if (trule->arg.trk_ctr.table.n)
7635 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007636 else
7637 target = curproxy;
7638
7639 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007640 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007641 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007642 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007643 cfgerr++;
7644 }
7645 else if (target->table.size == 0) {
7646 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007647 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007648 cfgerr++;
7649 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007650 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007651 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007652 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007653 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007654 cfgerr++;
7655 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007656 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007657 free(trule->arg.trk_ctr.table.n);
7658 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007659 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007660 * to pass a list of counters to track and allocate them right here using
7661 * stktable_alloc_data_type().
7662 */
7663 }
7664 }
7665
Willy Tarreaud1f96522010-08-03 19:34:32 +02007666 /* find the target table for 'tcp-request' layer 6 rules */
7667 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7668 struct proxy *target;
7669
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007670 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02007671 continue;
7672
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007673 if (trule->arg.trk_ctr.table.n)
7674 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007675 else
7676 target = curproxy;
7677
7678 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007679 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007680 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007681 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02007682 cfgerr++;
7683 }
7684 else if (target->table.size == 0) {
7685 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007686 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007687 cfgerr++;
7688 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007689 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007690 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007691 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007692 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007693 cfgerr++;
7694 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02007695 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007696 free(trule->arg.trk_ctr.table.n);
7697 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007698 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02007699 * to pass a list of counters to track and allocate them right here using
7700 * stktable_alloc_data_type().
7701 */
7702 }
7703 }
7704
Willy Tarreau09448f72014-06-25 18:12:15 +02007705 /* find the target table for 'http-request' layer 7 rules */
7706 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7707 struct proxy *target;
7708
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007709 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau09448f72014-06-25 18:12:15 +02007710 continue;
7711
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007712 if (hrqrule->arg.trk_ctr.table.n)
7713 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
Willy Tarreau09448f72014-06-25 18:12:15 +02007714 else
7715 target = curproxy;
7716
7717 if (!target) {
7718 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007719 curproxy->id, hrqrule->arg.trk_ctr.table.n,
Willy Tarreau09448f72014-06-25 18:12:15 +02007720 http_req_trk_idx(hrqrule->action));
7721 cfgerr++;
7722 }
7723 else if (target->table.size == 0) {
7724 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007725 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau09448f72014-06-25 18:12:15 +02007726 cfgerr++;
7727 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007728 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau09448f72014-06-25 18:12:15 +02007729 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007730 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau09448f72014-06-25 18:12:15 +02007731 http_req_trk_idx(hrqrule->action));
7732 cfgerr++;
7733 }
7734 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007735 free(hrqrule->arg.trk_ctr.table.n);
7736 hrqrule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau09448f72014-06-25 18:12:15 +02007737 /* Note: if we decide to enhance the track-sc syntax, we may be able
7738 * to pass a list of counters to track and allocate them right here using
7739 * stktable_alloc_data_type().
7740 */
7741 }
7742 }
7743
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02007744 /* move any "block" rules at the beginning of the http-request rules */
7745 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
7746 /* insert block_rules into http_req_rules at the beginning */
7747 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
7748 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
7749 curproxy->block_rules.n->p = &curproxy->http_req_rules;
7750 curproxy->http_req_rules.n = curproxy->block_rules.n;
7751 LIST_INIT(&curproxy->block_rules);
7752 }
7753
Emeric Brun32da3c42010-09-23 18:39:19 +02007754 if (curproxy->table.peers.name) {
7755 struct peers *curpeers = peers;
7756
7757 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
7758 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
7759 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01007760 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02007761 break;
7762 }
7763 }
7764
7765 if (!curpeers) {
7766 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
7767 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007768 free((void *)curproxy->table.peers.name);
7769 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007770 cfgerr++;
7771 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02007772 else if (curpeers->state == PR_STSTOPPED) {
7773 /* silently disable this peers section */
7774 curproxy->table.peers.p = NULL;
7775 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007776 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02007777 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
7778 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007779 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007780 cfgerr++;
7781 }
7782 }
7783
Simon Horman9dc49962015-01-30 11:22:59 +09007784
7785 if (curproxy->email_alert.mailers.name) {
7786 struct mailers *curmailers = mailers;
7787
7788 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
7789 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
7790 free(curproxy->email_alert.mailers.name);
7791 curproxy->email_alert.mailers.m = curmailers;
7792 curmailers->users++;
7793 break;
7794 }
7795 }
7796
7797 if (!curmailers) {
7798 Alert("Proxy '%s': unable to find mailers '%s'.\n",
7799 curproxy->id, curproxy->email_alert.mailers.name);
7800 free_email_alert(curproxy);
7801 cfgerr++;
7802 }
7803 }
7804
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007805 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01007806 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007807 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
7808 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
7809 "proxy", curproxy->id);
7810 cfgerr++;
7811 goto out_uri_auth_compat;
7812 }
7813
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007814 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007815 const char *uri_auth_compat_req[10];
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007816 struct act_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01007817 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007818
Willy Tarreau95fa4692010-02-01 13:05:50 +01007819 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
7820 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007821
7822 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007823 uri_auth_compat_req[i++] = "realm";
7824 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
7825 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007826
Willy Tarreau95fa4692010-02-01 13:05:50 +01007827 uri_auth_compat_req[i++] = "unless";
7828 uri_auth_compat_req[i++] = "{";
7829 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
7830 uri_auth_compat_req[i++] = "}";
7831 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007832
Willy Tarreauff011f22011-01-06 17:51:27 +01007833 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
7834 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007835 cfgerr++;
7836 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007837 }
7838
Willy Tarreauff011f22011-01-06 17:51:27 +01007839 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01007840
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007841 if (curproxy->uri_auth->auth_realm) {
7842 free(curproxy->uri_auth->auth_realm);
7843 curproxy->uri_auth->auth_realm = NULL;
7844 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007845
7846 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007847 }
7848out_uri_auth_compat:
7849
Dragan Dosen68d2e3a2015-09-19 22:35:44 +02007850 /* write a syslog header string that contains hostname, log_tag and pid */
Dragan Dosen1322d092015-09-22 16:05:32 +02007851 list_for_each_entry(tmplogsrv, &curproxy->logsrvs, list) {
7852 char *hdr;
7853 struct chunk *htp;
7854 char *htp_fmt;
7855 char *host = global.log_send_hostname;
Dragan Dosen68d2e3a2015-09-19 22:35:44 +02007856
Dragan Dosen1322d092015-09-22 16:05:32 +02007857 switch (tmplogsrv->format) {
7858 case LOG_FORMAT_RFC3164:
7859 hdr = logheader;
7860 htp = &curproxy->log_htp;
7861 htp_fmt = default_host_tag_pid_log_format;
7862 host = host ? host : "";
7863 break;
Dragan Dosen68d2e3a2015-09-19 22:35:44 +02007864
Dragan Dosen1322d092015-09-22 16:05:32 +02007865 case LOG_FORMAT_RFC5424:
7866 hdr = logheader_rfc5424;
7867 htp = &curproxy->log_htp_rfc5424;
7868 htp_fmt = rfc5424_host_tag_pid_log_format;
7869 break;
7870
7871 default:
7872 continue; /* must never happen */
7873 }
7874
7875 if (htp->str)
7876 continue;
7877
7878 if (!host) {
7879 int len = strlen(hostname);
7880 host = malloc(len + 2);
7881 snprintf(host, len + 2, "%s ", hostname);
7882 }
7883
7884 htp->str = lf_host_tag_pid(hdr, htp_fmt, host,
7885 curproxy->log_tag ? curproxy->log_tag : global.log_tag,
7886 pid, global.max_syslog_len);
7887
7888 if ((host != global.log_send_hostname) && strlen(host))
7889 free(host);
7890
7891 if ((htp->str == NULL) ||
7892 ((htp->len = htp->str - hdr) >= global.max_syslog_len)) {
7893 Alert("Proxy '%s': cannot write a syslog header string that contains "
7894 "hostname, log_tag and pid.\n",
7895 curproxy->id);
7896 cfgerr++;
7897 goto out_host_tag_pid;
7898 }
7899
7900 htp->str = (char *)malloc(htp->len);
7901 memcpy(htp->str, hdr, htp->len);
7902 htp->size = 0;
7903
7904 hdr[0] = 0;
7905 }
7906out_host_tag_pid:
Dragan Dosen68d2e3a2015-09-19 22:35:44 +02007907
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007908 /* compile the log format */
7909 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02007910 if (curproxy->conf.logformat_string != default_http_log_format &&
7911 curproxy->conf.logformat_string != default_tcp_log_format &&
7912 curproxy->conf.logformat_string != clf_http_log_format)
7913 free(curproxy->conf.logformat_string);
7914 curproxy->conf.logformat_string = NULL;
7915 free(curproxy->conf.lfs_file);
7916 curproxy->conf.lfs_file = NULL;
7917 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007918 }
7919
Willy Tarreau62a61232013-04-12 18:13:46 +02007920 if (curproxy->conf.logformat_string) {
7921 curproxy->conf.args.ctx = ARGC_LOG;
7922 curproxy->conf.args.file = curproxy->conf.lfs_file;
7923 curproxy->conf.args.line = curproxy->conf.lfs_line;
7924 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007925 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007926 curproxy->conf.args.file = NULL;
7927 curproxy->conf.args.line = 0;
7928 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007929
Willy Tarreau62a61232013-04-12 18:13:46 +02007930 if (curproxy->conf.uniqueid_format_string) {
7931 curproxy->conf.args.ctx = ARGC_UIF;
7932 curproxy->conf.args.file = curproxy->conf.uif_file;
7933 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01007934 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Godbachd9722032014-12-18 15:44:58 +08007935 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007936 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007937 curproxy->conf.args.file = NULL;
7938 curproxy->conf.args.line = 0;
7939 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007940
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007941 /* only now we can check if some args remain unresolved.
7942 * This must be done after the users and groups resolution.
7943 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007944 cfgerr += smp_resolve_args(curproxy);
7945 if (!cfgerr)
7946 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01007947
Willy Tarreau2738a142006-07-08 17:28:09 +02007948 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007949 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02007950 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02007951 (!curproxy->timeout.connect ||
7952 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007953 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02007954 " | While not properly invalid, you will certainly encounter various problems\n"
7955 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01007956 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007957 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007958 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02007959 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02007960
Willy Tarreau1fa31262007-12-03 00:36:16 +01007961 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
7962 * We must still support older configurations, so let's find out whether those
7963 * parameters have been set or must be copied from contimeouts.
7964 */
7965 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007966 if (!curproxy->timeout.tarpit ||
7967 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007968 /* tarpit timeout not set. We search in the following order:
7969 * default.tarpit, curr.connect, default.connect.
7970 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007971 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007972 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007973 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007974 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007975 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007976 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007977 }
7978 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007979 (!curproxy->timeout.queue ||
7980 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007981 /* queue timeout not set. We search in the following order:
7982 * default.queue, curr.connect, default.connect.
7983 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007984 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007985 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007986 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007987 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007988 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007989 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007990 }
7991 }
7992
Willy Tarreau1620ec32011-08-06 17:05:02 +02007993 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01007994 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
7995 curproxy->check_req = (char *)malloc(curproxy->check_len);
7996 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02007997 }
7998
Willy Tarreau215663d2014-06-13 18:30:23 +02007999 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
8000 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
8001 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
8002 proxy_type_str(curproxy), curproxy->id);
8003 err_code |= ERR_WARN;
8004 }
8005
Willy Tarreau193b8c62012-11-22 00:17:38 +01008006 /* ensure that cookie capture length is not too large */
8007 if (curproxy->capture_len >= global.tune.cookie_len) {
8008 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
8009 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
8010 err_code |= ERR_WARN;
8011 curproxy->capture_len = global.tune.cookie_len - 1;
8012 }
8013
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008014 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01008015 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008016 curproxy->req_cap_pool = create_pool("ptrcap",
8017 curproxy->nb_req_cap * sizeof(char *),
8018 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008019 }
8020
8021 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008022 curproxy->rsp_cap_pool = create_pool("ptrcap",
8023 curproxy->nb_rsp_cap * sizeof(char *),
8024 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008025 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008026
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02008027 switch (curproxy->load_server_state_from_file) {
8028 case PR_SRV_STATE_FILE_UNSPEC:
8029 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
8030 break;
8031 case PR_SRV_STATE_FILE_GLOBAL:
8032 if (!global.server_state_file) {
8033 Warning("config : backend '%s' configured to load server state file from global section 'server-state-file' directive. Unfortunately, 'server-state-file' is not set!\n",
8034 curproxy->id);
8035 err_code |= ERR_WARN;
8036 }
8037 break;
8038 }
8039
Willy Tarreaubaaee002006-06-26 02:48:02 +02008040 /* first, we will invert the servers list order */
8041 newsrv = NULL;
8042 while (curproxy->srv) {
8043 struct server *next;
8044
8045 next = curproxy->srv->next;
8046 curproxy->srv->next = newsrv;
8047 newsrv = curproxy->srv;
8048 if (!next)
8049 break;
8050 curproxy->srv = next;
8051 }
8052
Willy Tarreau17edc812014-01-03 12:14:34 +01008053 /* Check that no server name conflicts. This causes trouble in the stats.
8054 * We only emit a warning for the first conflict affecting each server,
8055 * in order to avoid combinatory explosion if all servers have the same
8056 * name. We do that only for servers which do not have an explicit ID,
8057 * because these IDs were made also for distinguishing them and we don't
8058 * want to annoy people who correctly manage them.
8059 */
8060 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
8061 struct server *other_srv;
8062
8063 if (newsrv->puid)
8064 continue;
8065
8066 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
8067 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
8068 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
8069 newsrv->conf.file, newsrv->conf.line,
8070 proxy_type_str(curproxy), curproxy->id,
8071 newsrv->id, other_srv->conf.line);
8072 break;
8073 }
8074 }
8075 }
8076
Willy Tarreaudd701652010-05-25 23:03:02 +02008077 /* assign automatic UIDs to servers which don't have one yet */
8078 next_id = 1;
8079 newsrv = curproxy->srv;
8080 while (newsrv != NULL) {
8081 if (!newsrv->puid) {
8082 /* server ID not set, use automatic numbering with first
8083 * spare entry starting with next_svid.
8084 */
8085 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
8086 newsrv->conf.id.key = newsrv->puid = next_id;
8087 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
8088 }
8089 next_id++;
8090 newsrv = newsrv->next;
8091 }
8092
Willy Tarreau20697042007-11-15 23:26:18 +01008093 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01008094 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02008095
Willy Tarreau62c3be22012-01-20 13:12:32 +01008096 /*
8097 * If this server supports a maxconn parameter, it needs a dedicated
8098 * tasks to fill the emptied slots when a connection leaves.
8099 * Also, resolve deferred tracking dependency if needed.
8100 */
8101 newsrv = curproxy->srv;
8102 while (newsrv != NULL) {
8103 if (newsrv->minconn > newsrv->maxconn) {
8104 /* Only 'minconn' was specified, or it was higher than or equal
8105 * to 'maxconn'. Let's turn this into maxconn and clean it, as
8106 * this will avoid further useless expensive computations.
8107 */
8108 newsrv->maxconn = newsrv->minconn;
8109 } else if (newsrv->maxconn && !newsrv->minconn) {
8110 /* minconn was not specified, so we set it to maxconn */
8111 newsrv->minconn = newsrv->maxconn;
8112 }
8113
Emeric Brun01f8e2f2012-05-18 16:02:00 +02008114#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02008115 if (newsrv->use_ssl || newsrv->check.use_ssl)
8116 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02008117#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02008118
Willy Tarreau2f075e92013-12-03 11:11:34 +01008119 /* set the check type on the server */
8120 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
8121
Willy Tarreau62c3be22012-01-20 13:12:32 +01008122 if (newsrv->trackit) {
8123 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02008124 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008125 char *pname, *sname;
8126
8127 pname = newsrv->trackit;
8128 sname = strrchr(pname, '/');
8129
8130 if (sname)
8131 *sname++ = '\0';
8132 else {
8133 sname = pname;
8134 pname = NULL;
8135 }
8136
8137 if (pname) {
Willy Tarreau9e0bb102015-05-26 11:24:42 +02008138 px = proxy_be_by_name(pname);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008139 if (!px) {
8140 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
8141 proxy_type_str(curproxy), curproxy->id,
8142 newsrv->id, pname);
8143 cfgerr++;
8144 goto next_srv;
8145 }
8146 } else
8147 px = curproxy;
8148
8149 srv = findserver(px, sname);
8150 if (!srv) {
8151 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
8152 proxy_type_str(curproxy), curproxy->id,
8153 newsrv->id, sname);
8154 cfgerr++;
8155 goto next_srv;
8156 }
8157
Willy Tarreau32091232014-05-16 13:52:00 +02008158 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
8159 !(srv->agent.state & CHK_ST_CONFIGURED) &&
8160 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01008161 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02008162 "tracking as it does not have any check nor agent enabled.\n",
8163 proxy_type_str(curproxy), curproxy->id,
8164 newsrv->id, px->id, srv->id);
8165 cfgerr++;
8166 goto next_srv;
8167 }
8168
8169 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
8170
8171 if (loop) {
8172 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
8173 "belongs to a tracking chain looping back to %s/%s.\n",
8174 proxy_type_str(curproxy), curproxy->id,
8175 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008176 cfgerr++;
8177 goto next_srv;
8178 }
8179
8180 if (curproxy != px &&
8181 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
8182 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
8183 "tracking: disable-on-404 option inconsistency.\n",
8184 proxy_type_str(curproxy), curproxy->id,
8185 newsrv->id, px->id, srv->id);
8186 cfgerr++;
8187 goto next_srv;
8188 }
8189
8190 /* if the other server is forced disabled, we have to do the same here */
Willy Tarreau20125212014-05-13 19:44:56 +02008191 if (srv->admin & SRV_ADMF_MAINT) {
Willy Tarreaua0066dd2014-05-16 11:25:16 +02008192 newsrv->admin |= SRV_ADMF_IMAINT;
Willy Tarreau892337c2014-05-13 23:41:20 +02008193 newsrv->state = SRV_ST_STOPPED;
Simon Horman125d0992013-02-24 17:23:38 +09008194 newsrv->check.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008195 }
8196
8197 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01008198 newsrv->tracknext = srv->trackers;
8199 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008200
8201 free(newsrv->trackit);
8202 newsrv->trackit = NULL;
8203 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008204
8205 /*
8206 * resolve server's resolvers name and update the resolvers pointer
8207 * accordingly
8208 */
8209 if (newsrv->resolvers_id) {
8210 struct dns_resolvers *curr_resolvers;
8211 int found;
8212
8213 found = 0;
8214 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
8215 if (!strcmp(curr_resolvers->id, newsrv->resolvers_id)) {
8216 found = 1;
8217 break;
8218 }
8219 }
8220
8221 if (!found) {
8222 Alert("config : %s '%s', server '%s': unable to find required resolvers '%s'\n",
8223 proxy_type_str(curproxy), curproxy->id,
8224 newsrv->id, newsrv->resolvers_id);
8225 cfgerr++;
8226 } else {
8227 free(newsrv->resolvers_id);
8228 newsrv->resolvers_id = NULL;
8229 if (newsrv->resolution)
8230 newsrv->resolution->resolvers = curr_resolvers;
8231 }
8232 }
8233 else {
8234 /* if no resolvers section associated to this server
8235 * we can clean up the associated resolution structure
8236 */
8237 if (newsrv->resolution) {
8238 free(newsrv->resolution->hostname_dn);
8239 newsrv->resolution->hostname_dn = NULL;
8240 free(newsrv->resolution);
8241 newsrv->resolution = NULL;
8242 }
8243 }
8244
Willy Tarreau62c3be22012-01-20 13:12:32 +01008245 next_srv:
8246 newsrv = newsrv->next;
8247 }
8248
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008249 /* We have to initialize the server lookup mechanism depending
8250 * on what LB algorithm was choosen.
8251 */
8252
8253 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
8254 switch (curproxy->lbprm.algo & BE_LB_KIND) {
8255 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02008256 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
8257 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8258 init_server_map(curproxy);
8259 } else {
8260 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
8261 fwrr_init_server_groups(curproxy);
8262 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008263 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008264
Willy Tarreau3ebb1162012-02-13 16:57:44 +01008265 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01008266 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
8267 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
8268 fwlc_init_server_tree(curproxy);
8269 } else {
8270 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
8271 fas_init_server_tree(curproxy);
8272 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008273 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008274
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008275 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008276 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
8277 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
8278 chash_init_server_tree(curproxy);
8279 } else {
8280 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8281 init_server_map(curproxy);
8282 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008283 break;
8284 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02008285
8286 if (curproxy->options & PR_O_LOGASAP)
8287 curproxy->to_log &= ~LW_BYTES;
8288
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008289 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01008290 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008291 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
8292 proxy_type_str(curproxy), curproxy->id);
8293 err_code |= ERR_WARN;
8294 }
8295
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008296 if (curproxy->mode != PR_MODE_HTTP) {
8297 int optnum;
8298
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008299 if (curproxy->uri_auth) {
8300 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
8301 proxy_type_str(curproxy), curproxy->id);
8302 err_code |= ERR_WARN;
8303 curproxy->uri_auth = NULL;
8304 }
8305
Willy Tarreau87cf5142011-08-19 22:57:24 +02008306 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008307 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8308 "forwardfor", proxy_type_str(curproxy), curproxy->id);
8309 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02008310 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008311 }
8312
8313 if (curproxy->options & PR_O_ORGTO) {
8314 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8315 "originalto", proxy_type_str(curproxy), curproxy->id);
8316 err_code |= ERR_WARN;
8317 curproxy->options &= ~PR_O_ORGTO;
8318 }
8319
8320 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
8321 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
8322 (curproxy->cap & cfg_opts[optnum].cap) &&
8323 (curproxy->options & cfg_opts[optnum].val)) {
8324 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8325 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
8326 err_code |= ERR_WARN;
8327 curproxy->options &= ~cfg_opts[optnum].val;
8328 }
8329 }
8330
8331 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
8332 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
8333 (curproxy->cap & cfg_opts2[optnum].cap) &&
8334 (curproxy->options2 & cfg_opts2[optnum].val)) {
8335 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8336 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
8337 err_code |= ERR_WARN;
8338 curproxy->options2 &= ~cfg_opts2[optnum].val;
8339 }
8340 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008341
Willy Tarreau29fbe512015-08-20 19:35:14 +02008342#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008343 if (curproxy->conn_src.bind_hdr_occ) {
8344 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008345 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01008346 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008347 err_code |= ERR_WARN;
8348 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008349#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008350 }
8351
Willy Tarreaubaaee002006-06-26 02:48:02 +02008352 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01008353 * ensure that we're not cross-dressing a TCP server into HTTP.
8354 */
8355 newsrv = curproxy->srv;
8356 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01008357 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008358 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
8359 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008360 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01008361 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008362
Willy Tarreau0cec3312011-10-31 13:49:26 +01008363 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
8364 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
8365 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8366 err_code |= ERR_WARN;
8367 }
8368
Willy Tarreauc93cd162014-05-13 15:54:22 +02008369 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02008370 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
8371 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8372 err_code |= ERR_WARN;
8373 }
8374
Willy Tarreau29fbe512015-08-20 19:35:14 +02008375#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008376 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
8377 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008378 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 +01008379 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008380 err_code |= ERR_WARN;
8381 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008382#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01008383 newsrv = newsrv->next;
8384 }
8385
Willy Tarreaue42bd962014-09-16 16:21:19 +02008386 /* check if we have a frontend with "tcp-request content" looking at L7
8387 * with no inspect-delay
8388 */
8389 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
8390 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008391 if (trule->action == ACT_TCP_CAPTURE &&
Thierry FOURNIERd0d65ae2015-08-04 08:21:12 +02008392 !(trule->arg.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008393 break;
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008394 if ((trule->action >= ACT_ACTION_TRK_SC0 && trule->action <= ACT_ACTION_TRK_SCMAX) &&
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008395 !(trule->arg.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008396 break;
8397 }
8398
8399 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
8400 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
8401 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
8402 " This means that these rules will randomly find their contents. This can be fixed by"
8403 " setting the tcp-request inspect-delay.\n",
8404 proxy_type_str(curproxy), curproxy->id);
8405 err_code |= ERR_WARN;
8406 }
8407 }
8408
Willy Tarreauc1a21672009-08-16 22:37:44 +02008409 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02008410 if (!curproxy->accept)
8411 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02008412
Willy Tarreauc1a21672009-08-16 22:37:44 +02008413 if (curproxy->tcp_req.inspect_delay ||
8414 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02008415 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008416
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008417 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008418 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008419 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008420 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008421
8422 /* both TCP and HTTP must check switching rules */
8423 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
8424 }
8425
8426 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02008427 if (curproxy->tcp_req.inspect_delay ||
8428 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
8429 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
8430
Emeric Brun97679e72010-09-23 17:56:44 +02008431 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
8432 curproxy->be_rsp_ana |= AN_RES_INSPECT;
8433
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008434 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008435 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008436 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008437 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008438
8439 /* If the backend does requires RDP cookie persistence, we have to
8440 * enable the corresponding analyser.
8441 */
8442 if (curproxy->options2 & PR_O2_RDPC_PRST)
8443 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
8444 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008445 }
8446
8447 /***********************************************************/
8448 /* At this point, target names have already been resolved. */
8449 /***********************************************************/
8450
8451 /* Check multi-process mode compatibility */
8452
8453 if (global.nbproc > 1 && global.stats_fe) {
8454 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8455 unsigned long mask;
8456
8457 mask = nbits(global.nbproc);
8458 if (global.stats_fe->bind_proc)
8459 mask &= global.stats_fe->bind_proc;
8460
8461 if (bind_conf->bind_proc)
8462 mask &= bind_conf->bind_proc;
8463
8464 /* stop here if more than one process is used */
David Carliere6c39412015-07-02 07:00:17 +00008465 if (my_popcountl(mask) > 1)
Willy Tarreau419ead82014-09-16 13:41:21 +02008466 break;
8467 }
8468 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
8469 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");
8470 }
8471 }
8472
8473 /* Make each frontend inherit bind-process from its listeners when not specified. */
8474 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8475 if (curproxy->bind_proc)
8476 continue;
8477
8478 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8479 unsigned long mask;
8480
Willy Tarreaue428b082015-05-04 21:57:58 +02008481 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008482 curproxy->bind_proc |= mask;
8483 }
8484
8485 if (!curproxy->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008486 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008487 }
8488
8489 if (global.stats_fe) {
8490 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8491 unsigned long mask;
8492
Willy Tarreaue428b082015-05-04 21:57:58 +02008493 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008494 global.stats_fe->bind_proc |= mask;
8495 }
8496 if (!global.stats_fe->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008497 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008498 }
8499
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02008500 /* propagate bindings from frontends to backends. Don't do it if there
8501 * are any fatal errors as we must not call it with unresolved proxies.
8502 */
8503 if (!cfgerr) {
8504 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8505 if (curproxy->cap & PR_CAP_FE)
8506 propagate_processes(curproxy, NULL);
8507 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008508 }
8509
8510 /* Bind each unbound backend to all processes when not specified. */
8511 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8512 if (curproxy->bind_proc)
8513 continue;
Willy Tarreaue428b082015-05-04 21:57:58 +02008514 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008515 }
8516
8517 /*******************************************************/
8518 /* At this step, all proxies have a non-null bind_proc */
8519 /*******************************************************/
8520
8521 /* perform the final checks before creating tasks */
8522
8523 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8524 struct listener *listener;
8525 unsigned int next_id;
8526 int nbproc;
8527
David Carliere6c39412015-07-02 07:00:17 +00008528 nbproc = my_popcountl(curproxy->bind_proc & nbits(global.nbproc));
Willy Tarreauc1a21672009-08-16 22:37:44 +02008529
Emeric Brunc52962f2012-11-15 18:28:02 +01008530#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008531 /* Configure SSL for each bind line.
8532 * Note: if configuration fails at some point, the ->ctx member
8533 * remains NULL so that listeners can later detach.
8534 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008535 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008536 int alloc_ctx;
8537
Emeric Brunc52962f2012-11-15 18:28:02 +01008538 if (!bind_conf->is_ssl) {
8539 if (bind_conf->default_ctx) {
8540 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
8541 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
8542 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008543 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01008544 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008545 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02008546 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008547 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008548 cfgerr++;
8549 continue;
8550 }
8551
Emeric Brun8dc60392014-05-09 13:52:00 +02008552 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008553 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02008554 if (alloc_ctx == SHCTX_E_INIT_LOCK)
8555 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");
8556 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008557 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02008558 cfgerr++;
8559 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008560 }
8561
Emeric Brunfc0421f2012-09-07 17:30:07 +02008562 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008563 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008564
8565 /* initialize CA variables if the certificates generation is enabled */
8566 cfgerr += ssl_sock_load_ca(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008567 }
Emeric Brunc52962f2012-11-15 18:28:02 +01008568#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008569
Willy Tarreaue6b98942007-10-29 01:09:36 +01008570 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008571 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008572 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008573 if (!listener->luid) {
8574 /* listener ID not set, use automatic numbering with first
8575 * spare entry starting with next_luid.
8576 */
8577 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
8578 listener->conf.id.key = listener->luid = next_id;
8579 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008580 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01008581 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008582
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008583 /* enable separate counters */
8584 if (curproxy->options2 & PR_O2_SOCKSTAT) {
8585 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01008586 if (!listener->name)
8587 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008588 }
Willy Tarreau81796be2012-09-22 19:11:47 +02008589
Willy Tarreaue6b98942007-10-29 01:09:36 +01008590 if (curproxy->options & PR_O_TCP_NOLING)
8591 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02008592 if (!listener->maxconn)
8593 listener->maxconn = curproxy->maxconn;
8594 if (!listener->backlog)
8595 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01008596 if (!listener->maxaccept)
8597 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
8598
8599 /* we want to have an optimal behaviour on single process mode to
8600 * maximize the work at once, but in multi-process we want to keep
8601 * some fairness between processes, so we target half of the max
8602 * number of events to be balanced over all the processes the proxy
8603 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
8604 * used to disable the limit.
8605 */
8606 if (listener->maxaccept > 0) {
8607 if (nbproc > 1)
8608 listener->maxaccept = (listener->maxaccept + 1) / 2;
8609 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
8610 }
8611
Willy Tarreau9903f0e2015-04-04 18:50:31 +02008612 listener->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02008613 listener->handler = process_stream;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008614 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01008615 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01008616
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008617 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
8618 listener->options |= LI_O_TCP_RULES;
8619
Willy Tarreaude3041d2010-05-31 10:56:17 +02008620 if (curproxy->mon_mask.s_addr)
8621 listener->options |= LI_O_CHK_MONNET;
8622
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008623 /* smart accept mode is automatic in HTTP mode */
8624 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008625 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008626 !(curproxy->no_options2 & PR_O2_SMARTACC)))
8627 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01008628 }
8629
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008630 /* Release unused SSL configs */
8631 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8632 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008633 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008634#ifdef USE_OPENSSL
Christopher Faulet31af49d2015-06-09 17:29:50 +02008635 ssl_sock_free_ca(bind_conf);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008636 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008637 free(bind_conf->ca_file);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008638 free(bind_conf->ca_sign_file);
8639 free(bind_conf->ca_sign_pass);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008640 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02008641 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008642 free(bind_conf->crl_file);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008643 if(bind_conf->keys_ref) {
8644 free(bind_conf->keys_ref->filename);
8645 free(bind_conf->keys_ref->tlskeys);
8646 free(bind_conf->keys_ref);
8647 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008648#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008649 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008650
Willy Tarreau102df612014-05-07 23:56:38 +02008651 if (nbproc > 1) {
8652 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02008653 int count, maxproc = 0;
8654
8655 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
David Carliere6c39412015-07-02 07:00:17 +00008656 count = my_popcountl(bind_conf->bind_proc);
Willy Tarreaueb791e02014-09-16 15:11:04 +02008657 if (count > maxproc)
8658 maxproc = count;
8659 }
8660 /* backends have 0, frontends have 1 or more */
8661 if (maxproc != 1)
8662 Warning("Proxy '%s': in multi-process mode, stats will be"
8663 " limited to process assigned to the current request.\n",
8664 curproxy->id);
8665
Willy Tarreau102df612014-05-07 23:56:38 +02008666 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
8667 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
8668 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008669 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008670 }
Willy Tarreau102df612014-05-07 23:56:38 +02008671 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
8672 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
8673 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008674 }
8675 }
Willy Tarreau918ff602011-07-25 16:33:49 +02008676
8677 /* create the task associated with the proxy */
8678 curproxy->task = task_new();
8679 if (curproxy->task) {
8680 curproxy->task->context = curproxy;
8681 curproxy->task->process = manage_proxy;
8682 /* no need to queue, it will be done automatically if some
8683 * listener gets limited.
8684 */
8685 curproxy->task->expire = TICK_ETERNITY;
8686 } else {
8687 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
8688 curproxy->id);
8689 cfgerr++;
8690 }
Willy Tarreaub369a042014-09-16 13:21:03 +02008691 }
8692
Willy Tarreaufbb78422011-06-05 15:38:35 +02008693 /* automatically compute fullconn if not set. We must not do it in the
8694 * loop above because cross-references are not yet fully resolved.
8695 */
8696 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8697 /* If <fullconn> is not set, let's set it to 10% of the sum of
8698 * the possible incoming frontend's maxconns.
8699 */
8700 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
8701 struct proxy *fe;
8702 int total = 0;
8703
8704 /* sum up the number of maxconns of frontends which
8705 * reference this backend at least once or which are
8706 * the same one ('listen').
8707 */
8708 for (fe = proxy; fe; fe = fe->next) {
8709 struct switching_rule *rule;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008710 int found = 0;
8711
8712 if (!(fe->cap & PR_CAP_FE))
8713 continue;
8714
8715 if (fe == curproxy) /* we're on a "listen" instance */
8716 found = 1;
8717
8718 if (fe->defbe.be == curproxy) /* "default_backend" */
8719 found = 1;
8720
8721 /* check if a "use_backend" rule matches */
8722 if (!found) {
8723 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01008724 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02008725 found = 1;
8726 break;
8727 }
8728 }
8729 }
8730
Willy Tarreaufbb78422011-06-05 15:38:35 +02008731 /* now we've checked all possible ways to reference a backend
8732 * from a frontend.
8733 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02008734 if (!found)
8735 continue;
8736 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008737 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02008738 /* we have the sum of the maxconns in <total>. We only
8739 * keep 10% of that sum to set the default fullconn, with
8740 * a hard minimum of 1 (to avoid a divide by zero).
8741 */
8742 curproxy->fullconn = (total + 9) / 10;
8743 if (!curproxy->fullconn)
8744 curproxy->fullconn = 1;
8745 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01008746 }
8747
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008748 /*
8749 * Recount currently required checks.
8750 */
8751
8752 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
8753 int optnum;
8754
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008755 for (optnum = 0; cfg_opts[optnum].name; optnum++)
8756 if (curproxy->options & cfg_opts[optnum].val)
8757 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008758
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008759 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
8760 if (curproxy->options2 & cfg_opts2[optnum].val)
8761 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008762 }
8763
Willy Tarreau0fca4832015-05-01 19:12:05 +02008764 /* compute the required process bindings for the peers */
8765 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
8766 if (curproxy->table.peers.p)
8767 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
8768
Willy Tarreau122541c2011-09-07 21:24:49 +02008769 if (peers) {
8770 struct peers *curpeers = peers, **last;
8771 struct peer *p, *pb;
8772
Willy Tarreau1e273012015-05-01 19:15:17 +02008773 /* Remove all peers sections which don't have a valid listener,
8774 * which are not used by any table, or which are bound to more
8775 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02008776 */
8777 last = &peers;
8778 while (*last) {
8779 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008780
8781 if (curpeers->state == PR_STSTOPPED) {
8782 /* the "disabled" keyword was present */
8783 if (curpeers->peers_fe)
8784 stop_proxy(curpeers->peers_fe);
8785 curpeers->peers_fe = NULL;
8786 }
8787 else if (!curpeers->peers_fe) {
8788 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
8789 curpeers->id, localpeer);
8790 }
David Carliere6c39412015-07-02 07:00:17 +00008791 else if (my_popcountl(curpeers->peers_fe->bind_proc) != 1) {
Willy Tarreau1e273012015-05-01 19:15:17 +02008792 /* either it's totally stopped or too much used */
8793 if (curpeers->peers_fe->bind_proc) {
8794 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreau64c57222015-05-04 21:48:51 +02008795 "running in different processes (%d different ones). "
8796 "Check global.nbproc and all tables' bind-process "
David Carliere6c39412015-07-02 07:00:17 +00008797 "settings.\n", curpeers->id, my_popcountl(curpeers->peers_fe->bind_proc));
Willy Tarreau1e273012015-05-01 19:15:17 +02008798 cfgerr++;
8799 }
8800 stop_proxy(curpeers->peers_fe);
8801 curpeers->peers_fe = NULL;
8802 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008803 else {
Emeric Brunb3971ab2015-05-12 18:49:09 +02008804 peers_init_sync(curpeers);
Willy Tarreau122541c2011-09-07 21:24:49 +02008805 last = &curpeers->next;
8806 continue;
8807 }
8808
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008809 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02008810 p = curpeers->remote;
8811 while (p) {
8812 pb = p->next;
8813 free(p->id);
8814 free(p);
8815 p = pb;
8816 }
8817
8818 /* Destroy and unlink this curpeers section.
8819 * Note: curpeers is backed up into *last.
8820 */
8821 free(curpeers->id);
8822 curpeers = curpeers->next;
8823 free(*last);
8824 *last = curpeers;
8825 }
8826 }
8827
Willy Tarreau6866f3f2015-05-01 19:09:08 +02008828 /* initialize stick-tables on backend capable proxies. This must not
8829 * be done earlier because the data size may be discovered while parsing
8830 * other proxies.
8831 */
8832 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8833 if (curproxy->state == PR_STSTOPPED)
8834 continue;
8835
8836 if (!stktable_init(&curproxy->table)) {
8837 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
8838 cfgerr++;
8839 }
8840 }
8841
Simon Horman0d16a402015-01-30 11:22:58 +09008842 if (mailers) {
8843 struct mailers *curmailers = mailers, **last;
8844 struct mailer *m, *mb;
8845
8846 /* Remove all mailers sections which don't have a valid listener.
8847 * This can happen when a mailers section is never referenced.
8848 */
8849 last = &mailers;
8850 while (*last) {
8851 curmailers = *last;
8852 if (curmailers->users) {
8853 last = &curmailers->next;
8854 continue;
8855 }
8856
8857 Warning("Removing incomplete section 'mailers %s'.\n",
8858 curmailers->id);
8859
8860 m = curmailers->mailer_list;
8861 while (m) {
8862 mb = m->next;
8863 free(m->id);
8864 free(m);
8865 m = mb;
8866 }
8867
8868 /* Destroy and unlink this curmailers section.
8869 * Note: curmailers is backed up into *last.
8870 */
8871 free(curmailers->id);
8872 curmailers = curmailers->next;
8873 free(*last);
8874 *last = curmailers;
8875 }
8876 }
8877
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02008878 /* Update server_state_file_name to backend name if backend is supposed to use
8879 * a server-state file locally defined and none has been provided */
8880 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8881 if (curproxy->load_server_state_from_file == PR_SRV_STATE_FILE_LOCAL &&
8882 curproxy->server_state_file_name == NULL)
8883 curproxy->server_state_file_name = strdup(curproxy->id);
8884 }
8885
Willy Tarreau34eb6712011-10-24 18:15:04 +02008886 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02008887 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02008888 MEM_F_SHARED);
8889
Willy Tarreaubb925012009-07-23 13:36:36 +02008890 if (cfgerr > 0)
8891 err_code |= ERR_ALERT | ERR_FATAL;
8892 out:
8893 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02008894}
8895
Willy Tarreau5b2c3362008-07-09 19:39:06 +02008896/*
8897 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
8898 * parsing sessions.
8899 */
8900void cfg_register_keywords(struct cfg_kw_list *kwl)
8901{
8902 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
8903}
Willy Tarreaubaaee002006-06-26 02:48:02 +02008904
Willy Tarreau5b2c3362008-07-09 19:39:06 +02008905/*
8906 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
8907 */
8908void cfg_unregister_keywords(struct cfg_kw_list *kwl)
8909{
8910 LIST_DEL(&kwl->list);
8911 LIST_INIT(&kwl->list);
8912}
Willy Tarreaubaaee002006-06-26 02:48:02 +02008913
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01008914/* this function register new section in the haproxy configuration file.
8915 * <section_name> is the name of this new section and <section_parser>
8916 * is the called parser. If two section declaration have the same name,
8917 * only the first declared is used.
8918 */
8919int cfg_register_section(char *section_name,
8920 int (*section_parser)(const char *, int, char **, int))
8921{
8922 struct cfg_section *cs;
8923
8924 cs = calloc(1, sizeof(*cs));
8925 if (!cs) {
8926 Alert("register section '%s': out of memory.\n", section_name);
8927 return 0;
8928 }
8929
8930 cs->section_name = section_name;
8931 cs->section_parser = section_parser;
8932
8933 LIST_ADDQ(&sections, &cs->list);
8934
8935 return 1;
8936}
8937
Willy Tarreaubaaee002006-06-26 02:48:02 +02008938/*
David Carlier845efb52015-09-25 11:49:18 +01008939 * free all config section entries
8940 */
8941void cfg_unregister_sections(void)
8942{
8943 struct cfg_section *cs, *ics;
8944
8945 list_for_each_entry_safe(cs, ics, &sections, list) {
8946 LIST_DEL(&cs->list);
8947 free(cs);
8948 }
8949}
8950
8951/*
Willy Tarreaubaaee002006-06-26 02:48:02 +02008952 * Local variables:
8953 * c-indent-level: 8
8954 * c-basic-offset: 8
8955 * End:
8956 */