blob: 44b1c2ca33371725834a97e990bd2bfe0d8f4757 [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>
Willy Tarreaubaaee002006-06-26 02:48:02 +020052
Willy Tarreaueb0c6142007-05-07 00:53:22 +020053#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010054#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020055#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020056#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020057#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020058#include <proto/compression.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020059#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020060#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020061#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020062#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010063#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020064#include <proto/lb_fwlc.h>
65#include <proto/lb_fwrr.h>
66#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020067#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020068#include <proto/log.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020069#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010070#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020071#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010072#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010073#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020074#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020075#include <proto/sample.h>
Willy Tarreau9903f0e2015-04-04 18:50:31 +020076#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020077#include <proto/server.h>
Willy Tarreau87b09662015-04-03 00:22:06 +020078#include <proto/stream.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020079#include <proto/raw_sock.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020080#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010081#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020082
Emeric Brunfc0421f2012-09-07 17:30:07 +020083#ifdef USE_OPENSSL
84#include <types/ssl_sock.h>
85#include <proto/ssl_sock.h>
86#include <proto/shctx.h>
87#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020088
Willy Tarreauf3c69202006-07-09 16:42:34 +020089/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
90 * ssl-hello-chk option to ensure that the remote server speaks SSL.
91 *
92 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
93 */
94const char sslv3_client_hello_pkt[] = {
95 "\x16" /* ContentType : 0x16 = Hanshake */
96 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
97 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
98 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
99 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
100 "\x03\x00" /* Hello Version : 0x0300 = v3 */
101 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
102 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
103 "\x00" /* Session ID length : empty (no session ID) */
104 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
105 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
106 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
107 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
108 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
109 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
110 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
111 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
112 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
113 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
114 "\x00\x38" "\x00\x39" "\x00\x3A"
115 "\x01" /* Compression Length : 0x01 = 1 byte for types */
116 "\x00" /* Compression Type : 0x00 = NULL compression */
117};
118
Willy Tarreau3842f002009-06-14 11:39:52 +0200119/* various keyword modifiers */
120enum kw_mod {
121 KWM_STD = 0, /* normal */
122 KWM_NO, /* "no" prefixed before the keyword */
123 KWM_DEF, /* "default" prefixed before the keyword */
124};
125
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +0100126/* permit to store configuration section */
127struct cfg_section {
128 struct list list;
129 char *section_name;
130 int (*section_parser)(const char *, int, char **, int);
131};
132
133/* Used to chain configuration sections definitions. This list
134 * stores struct cfg_section
135 */
136struct list sections = LIST_HEAD_INIT(sections);
137
Willy Tarreau13943ab2006-12-31 00:24:10 +0100138/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100139struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100140 const char *name;
141 unsigned int val;
142 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100143 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100144 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100145};
146
147/* proxy->options */
148static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100149{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100150 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
151 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
152 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
153 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
154 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
155 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100156 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau9fbe18e2015-05-01 22:42:08 +0200157 { "http-buffer-request", PR_O_WREQ_BODY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau0f228a02015-05-01 15:37:53 +0200158 { "http-ignore-probes", PR_O_IGNORE_PRB, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreau9420b122013-12-15 18:58:25 +0100159 { "prefer-last-server", PR_O_PREF_LAST, PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100160 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
161 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
162 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100163 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100164#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100165 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100166#else
167 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100168#endif
169
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100170 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100171};
172
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100173/* proxy->options2 */
174static const struct cfg_opt cfg_opts2[] =
175{
176#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100177 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
178 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
179 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100180#else
181 { "splice-request", 0, 0, 0, 0 },
182 { "splice-response", 0, 0, 0, 0 },
183 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100184#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100185 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
186 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
187 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
188 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
189 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
190 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
191 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
192 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
193 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400194 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100195 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200196 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200197 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100198 { NULL, 0, 0, 0 }
199};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200200
Willy Tarreau6daf3432008-01-22 16:44:08 +0100201static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200202static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
203int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100204int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200205
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200206/* List head of all known configuration keywords */
207static struct cfg_kw_list cfg_keywords = {
208 .list = LIST_HEAD_INIT(cfg_keywords.list)
209};
210
Willy Tarreaubaaee002006-06-26 02:48:02 +0200211/*
212 * converts <str> to a list of listeners which are dynamically allocated.
213 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
214 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
215 * - <port> is a numerical port from 1 to 65535 ;
216 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
217 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200218 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
219 * not NULL, it must be a valid pointer to either NULL or a freeable area that
220 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200221 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200222int 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 +0200223{
224 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100225 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200226 int port, end;
227
228 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200229
Willy Tarreaubaaee002006-06-26 02:48:02 +0200230 while (next && *next) {
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100231 struct sockaddr_storage ss, *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100232 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200233
234 str = next;
235 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100236 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200237 *next++ = 0;
238 }
239
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100240 ss2 = str2sa_range(str, &port, &end, err,
241 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix);
242 if (!ss2)
243 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200244
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100245 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100246 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200247 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100248 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200249 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200250
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100251 if (!port || !end) {
252 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
253 goto fail;
254 }
255
Emeric Bruned760922010-10-22 17:59:25 +0200256 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200257 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200258 goto fail;
259 }
260
261 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200262 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200263 goto fail;
264 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200265 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100266 else if (ss2->ss_family == AF_UNSPEC) {
267 socklen_t addr_len;
268
269 /* We want to attach to an already bound fd whose number
270 * is in the addr part of ss2 when cast to sockaddr_in.
271 * Note that by definition there is a single listener.
272 * We still have to determine the address family to
273 * register the correct protocol.
274 */
275 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
276 addr_len = sizeof(*ss2);
277 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
278 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
279 goto fail;
280 }
281
282 port = end = get_host_port(ss2);
283 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200284
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100285 /* OK the address looks correct */
286 ss = *ss2;
287
Willy Tarreaubaaee002006-06-26 02:48:02 +0200288 for (; port <= end; port++) {
289 l = (struct listener *)calloc(1, sizeof(struct listener));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100290 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200291 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
292 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
293 l->frontend = curproxy;
294 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200295
Willy Tarreau40aa0702013-03-10 23:51:38 +0100296 l->fd = fd;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200297 l->addr = ss;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200298 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100299 l->state = LI_INIT;
300
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100301 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200302 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100303 tcpv4_add_listener(l);
304 }
Emeric Bruned760922010-10-22 17:59:25 +0200305 else if (ss.ss_family == AF_INET6) {
306 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
307 tcpv6_add_listener(l);
308 }
309 else {
Emeric Bruned760922010-10-22 17:59:25 +0200310 uxst_add_listener(l);
311 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200312
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200313 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100314 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200315 } /* end for(port) */
316 } /* end while(next) */
317 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200318 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200319 fail:
320 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200321 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200322}
323
William Lallemand6e62fb62015-04-28 16:55:23 +0200324/*
325 * Report a fatal Alert when there is too much arguments
326 * The index is the current keyword in args
327 * Return 0 if the number of argument is correct, otherwise emit an alert and return 1
328 * Fill err_code with an ERR_ALERT and an ERR_FATAL
329 */
330int alertif_too_many_args_idx(int maxarg, int index, const char *file, int linenum, char **args, int *err_code)
331{
332 char *kw = NULL;
333 int i;
334
335 if (!*args[index + maxarg + 1])
336 return 0;
337
338 memprintf(&kw, "%s", args[0]);
339 for (i = 1; i <= index; i++) {
340 memprintf(&kw, "%s %s", kw, args[i]);
341 }
342
343 Alert("parsing [%s:%d] : '%s' cannot handle unexpected argument '%s'.\n", file, linenum, kw, args[index + maxarg + 1]);
344 free(kw);
345 *err_code |= ERR_ALERT | ERR_FATAL;
346 return 1;
347}
348
349/*
350 * same as alertif_too_many_args_idx with a 0 index
351 */
352int alertif_too_many_args(int maxarg, const char *file, int linenum, char **args, int *err_code)
353{
354 return alertif_too_many_args_idx(maxarg, 0, file, linenum, args, err_code);
355}
356
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200357/* Report a warning if a rule is placed after a 'tcp-request content' rule.
358 * Return 1 if the warning has been emitted, otherwise 0.
359 */
360int warnif_rule_after_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
361{
362 if (!LIST_ISEMPTY(&proxy->tcp_req.inspect_rules)) {
363 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request content' rule will still be processed before.\n",
364 file, line, arg);
365 return 1;
366 }
367 return 0;
368}
369
Willy Tarreau61d18892009-03-31 10:49:21 +0200370/* Report a warning if a rule is placed after a 'block' rule.
371 * Return 1 if the warning has been emitted, otherwise 0.
372 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100373int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200374{
Willy Tarreau353bc9f2014-04-28 22:05:31 +0200375 if (!LIST_ISEMPTY(&proxy->block_rules)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200376 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
377 file, line, arg);
378 return 1;
379 }
380 return 0;
381}
382
Willy Tarreau5002f572014-04-23 01:32:02 +0200383/* Report a warning if a rule is placed after an 'http_request' rule.
384 * Return 1 if the warning has been emitted, otherwise 0.
385 */
386int warnif_rule_after_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
387{
388 if (!LIST_ISEMPTY(&proxy->http_req_rules)) {
389 Warning("parsing [%s:%d] : a '%s' rule placed after an 'http-request' rule will still be processed before.\n",
390 file, line, arg);
391 return 1;
392 }
393 return 0;
394}
395
Willy Tarreau61d18892009-03-31 10:49:21 +0200396/* Report a warning if a rule is placed after a reqrewrite rule.
397 * Return 1 if the warning has been emitted, otherwise 0.
398 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100399int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200400{
401 if (proxy->req_exp) {
402 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
403 file, line, arg);
404 return 1;
405 }
406 return 0;
407}
408
409/* Report a warning if a rule is placed after a reqadd rule.
410 * Return 1 if the warning has been emitted, otherwise 0.
411 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100412int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200413{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100414 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200415 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
416 file, line, arg);
417 return 1;
418 }
419 return 0;
420}
421
422/* Report a warning if a rule is placed after a redirect rule.
423 * Return 1 if the warning has been emitted, otherwise 0.
424 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100425int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200426{
427 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
428 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
429 file, line, arg);
430 return 1;
431 }
432 return 0;
433}
434
435/* Report a warning if a rule is placed after a 'use_backend' rule.
436 * Return 1 if the warning has been emitted, otherwise 0.
437 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100438int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200439{
440 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
441 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
442 file, line, arg);
443 return 1;
444 }
445 return 0;
446}
447
Willy Tarreauee445d92014-04-23 01:39:04 +0200448/* Report a warning if a rule is placed after a 'use-server' rule.
449 * Return 1 if the warning has been emitted, otherwise 0.
450 */
451int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line, const char *arg)
452{
453 if (!LIST_ISEMPTY(&proxy->server_rules)) {
454 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use-server' rule will still be processed before.\n",
455 file, line, arg);
456 return 1;
457 }
458 return 0;
459}
460
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200461/* report a warning if a "tcp request connection" rule is dangerously placed */
462int warnif_misplaced_tcp_conn(struct proxy *proxy, const char *file, int line, const char *arg)
463{
464 return warnif_rule_after_tcp_cont(proxy, file, line, arg) ||
465 warnif_rule_after_block(proxy, file, line, arg) ||
466 warnif_rule_after_http_req(proxy, file, line, arg) ||
467 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
468 warnif_rule_after_reqadd(proxy, file, line, arg) ||
469 warnif_rule_after_redirect(proxy, file, line, arg) ||
470 warnif_rule_after_use_backend(proxy, file, line, arg) ||
471 warnif_rule_after_use_server(proxy, file, line, arg);
472}
473
474/* report a warning if a "tcp request content" rule is dangerously placed */
475int warnif_misplaced_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
476{
477 return warnif_rule_after_block(proxy, file, line, arg) ||
478 warnif_rule_after_http_req(proxy, file, line, arg) ||
479 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
480 warnif_rule_after_reqadd(proxy, file, line, arg) ||
481 warnif_rule_after_redirect(proxy, file, line, arg) ||
482 warnif_rule_after_use_backend(proxy, file, line, arg) ||
483 warnif_rule_after_use_server(proxy, file, line, arg);
484}
485
Willy Tarreau61d18892009-03-31 10:49:21 +0200486/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100487int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200488{
Willy Tarreau5002f572014-04-23 01:32:02 +0200489 return warnif_rule_after_http_req(proxy, file, line, arg) ||
490 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
491 warnif_rule_after_reqadd(proxy, file, line, arg) ||
492 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200493 warnif_rule_after_use_backend(proxy, file, line, arg) ||
494 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau5002f572014-04-23 01:32:02 +0200495}
496
497/* report a warning if an http-request rule is dangerously placed */
498int warnif_misplaced_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
499{
Willy Tarreau61d18892009-03-31 10:49:21 +0200500 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
501 warnif_rule_after_reqadd(proxy, file, line, arg) ||
502 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200503 warnif_rule_after_use_backend(proxy, file, line, arg) ||
504 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200505}
506
507/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100508int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200509{
510 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
511 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200512 warnif_rule_after_use_backend(proxy, file, line, arg) ||
513 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200514}
515
516/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100517int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200518{
519 return warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200520 warnif_rule_after_use_backend(proxy, file, line, arg) ||
521 warnif_rule_after_use_server(proxy, file, line, arg);
522}
523
524/* report a warning if a redirect rule is dangerously placed */
525int warnif_misplaced_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
526{
527 return warnif_rule_after_use_backend(proxy, file, line, arg) ||
528 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200529}
530
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100531/* Report it if a request ACL condition uses some keywords that are incompatible
532 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
533 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
534 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100535 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100536static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100537{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100538 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200539 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100540
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100541 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100542 return 0;
543
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100544 acl = acl_cond_conflicts(cond, where);
545 if (acl) {
546 if (acl->name && *acl->name)
547 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
548 file, line, acl->name, sample_ckp_names(where));
549 else
550 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 +0200551 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100552 return ERR_WARN;
553 }
554 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100555 return 0;
556
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100557 if (acl->name && *acl->name)
558 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200559 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100560 else
561 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200562 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100563 return ERR_WARN;
564}
565
Willy Tarreaubaaee002006-06-26 02:48:02 +0200566/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200567 * parse a line in a <global> section. Returns the error code, 0 if OK, or
568 * any combination of :
569 * - ERR_ABORT: must abort ASAP
570 * - ERR_FATAL: we can continue parsing but not start the service
571 * - ERR_WARN: a warning has been emitted
572 * - ERR_ALERT: an alert has been emitted
573 * Only the two first ones can stop processing, the two others are just
574 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200575 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200576int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200577{
Willy Tarreau058e9072009-07-20 09:30:05 +0200578 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200579 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200580
581 if (!strcmp(args[0], "global")) { /* new section */
582 /* no option, nothing special to do */
William Lallemand6e62fb62015-04-28 16:55:23 +0200583 alertif_too_many_args(0, file, linenum, args, &err_code);
Willy Tarreau058e9072009-07-20 09:30:05 +0200584 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200585 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200586 else if (!strcmp(args[0], "ca-base")) {
587#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +0200588 if(alertif_too_many_args(1, file, linenum, args, &err_code))
589 goto out;
Emeric Brunc8e8d122012-10-02 18:42:10 +0200590 if (global.ca_base != NULL) {
591 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
592 err_code |= ERR_ALERT;
593 goto out;
594 }
595 if (*(args[1]) == 0) {
596 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
597 err_code |= ERR_ALERT | ERR_FATAL;
598 goto out;
599 }
600 global.ca_base = strdup(args[1]);
601#else
602 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
603 err_code |= ERR_ALERT | ERR_FATAL;
604 goto out;
605#endif
606 }
607 else if (!strcmp(args[0], "crt-base")) {
608#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +0200609 if (alertif_too_many_args(1, file, linenum, args, &err_code))
610 goto out;
Emeric Brunc8e8d122012-10-02 18:42:10 +0200611 if (global.crt_base != NULL) {
612 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
613 err_code |= ERR_ALERT;
614 goto out;
615 }
616 if (*(args[1]) == 0) {
617 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
618 err_code |= ERR_ALERT | ERR_FATAL;
619 goto out;
620 }
621 global.crt_base = strdup(args[1]);
622#else
623 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
624 err_code |= ERR_ALERT | ERR_FATAL;
625 goto out;
626#endif
627 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200628 else if (!strcmp(args[0], "daemon")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200629 if (alertif_too_many_args(0, file, linenum, args, &err_code))
630 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200631 global.mode |= MODE_DAEMON;
632 }
633 else if (!strcmp(args[0], "debug")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200634 if (alertif_too_many_args(0, file, linenum, args, &err_code))
635 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200636 global.mode |= MODE_DEBUG;
637 }
638 else if (!strcmp(args[0], "noepoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200639 if (alertif_too_many_args(0, file, linenum, args, &err_code))
640 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100641 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200642 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200643 else if (!strcmp(args[0], "nokqueue")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200644 if (alertif_too_many_args(0, file, linenum, args, &err_code))
645 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100646 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200647 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200648 else if (!strcmp(args[0], "nopoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200649 if (alertif_too_many_args(0, file, linenum, args, &err_code))
650 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100651 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200652 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100653 else if (!strcmp(args[0], "nosplice")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200654 if (alertif_too_many_args(0, file, linenum, args, &err_code))
655 goto out;
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100656 global.tune.options &= ~GTUNE_USE_SPLICE;
657 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200658 else if (!strcmp(args[0], "nogetaddrinfo")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200659 if (alertif_too_many_args(0, file, linenum, args, &err_code))
660 goto out;
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200661 global.tune.options &= ~GTUNE_USE_GAI;
662 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200663 else if (!strcmp(args[0], "quiet")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200664 if (alertif_too_many_args(0, file, linenum, args, &err_code))
665 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200666 global.mode |= MODE_QUIET;
667 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200668 else if (!strcmp(args[0], "tune.maxpollevents")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200669 if (alertif_too_many_args(1, file, linenum, args, &err_code))
670 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200671 if (global.tune.maxpollevents != 0) {
672 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200673 err_code |= ERR_ALERT;
674 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200675 }
676 if (*(args[1]) == 0) {
677 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200678 err_code |= ERR_ALERT | ERR_FATAL;
679 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200680 }
681 global.tune.maxpollevents = atol(args[1]);
682 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100683 else if (!strcmp(args[0], "tune.maxaccept")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200684 if (alertif_too_many_args(1, file, linenum, args, &err_code))
685 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100686 if (global.tune.maxaccept != 0) {
687 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200688 err_code |= ERR_ALERT;
689 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100690 }
691 if (*(args[1]) == 0) {
692 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200693 err_code |= ERR_ALERT | ERR_FATAL;
694 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100695 }
696 global.tune.maxaccept = atol(args[1]);
697 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200698 else if (!strcmp(args[0], "tune.chksize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200699 if (alertif_too_many_args(1, file, linenum, args, &err_code))
700 goto out;
Willy Tarreau43961d52010-10-04 20:39:20 +0200701 if (*(args[1]) == 0) {
702 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
703 err_code |= ERR_ALERT | ERR_FATAL;
704 goto out;
705 }
706 global.tune.chksize = atol(args[1]);
707 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200708#ifdef USE_OPENSSL
Emeric Brun8dc60392014-05-09 13:52:00 +0200709 else if (!strcmp(args[0], "tune.ssl.force-private-cache")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200710 if (alertif_too_many_args(0, file, linenum, args, &err_code))
711 goto out;
Emeric Brun8dc60392014-05-09 13:52:00 +0200712 global.tune.sslprivatecache = 1;
713 }
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100714 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200715 if (alertif_too_many_args(1, file, linenum, args, &err_code))
716 goto out;
Emeric Brunfc32aca2012-09-03 12:10:29 +0200717 if (*(args[1]) == 0) {
718 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
719 err_code |= ERR_ALERT | ERR_FATAL;
720 goto out;
721 }
722 global.tune.sslcachesize = atol(args[1]);
723 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100724 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
725 unsigned int ssllifetime;
726 const char *res;
727
William Lallemand1a748ae2015-05-19 16:37:23 +0200728 if (alertif_too_many_args(1, file, linenum, args, &err_code))
729 goto out;
Emeric Brun4f65bff2012-11-16 15:11:00 +0100730 if (*(args[1]) == 0) {
731 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
732 err_code |= ERR_ALERT | ERR_FATAL;
733 goto out;
734 }
735
736 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
737 if (res) {
738 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
739 file, linenum, *res, args[0]);
740 err_code |= ERR_ALERT | ERR_FATAL;
741 goto out;
742 }
743
744 global.tune.ssllifetime = ssllifetime;
745 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100746 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200747 if (alertif_too_many_args(1, file, linenum, args, &err_code))
748 goto out;
Willy Tarreaubfd59462013-02-21 07:46:09 +0100749 if (*(args[1]) == 0) {
750 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
751 err_code |= ERR_ALERT | ERR_FATAL;
752 goto out;
753 }
754 global.tune.ssl_max_record = atol(args[1]);
755 }
Remi Gacogne47783ef2015-05-29 15:53:22 +0200756#ifndef OPENSSL_NO_DH
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200757 else if (!strcmp(args[0], "tune.ssl.default-dh-param")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200758 if (alertif_too_many_args(1, file, linenum, args, &err_code))
759 goto out;
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200760 if (*(args[1]) == 0) {
761 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
762 err_code |= ERR_ALERT | ERR_FATAL;
763 goto out;
764 }
765 global.tune.ssl_default_dh_param = atol(args[1]);
766 if (global.tune.ssl_default_dh_param < 1024) {
767 Alert("parsing [%s:%d] : '%s' expects a value >= 1024.\n", file, linenum, args[0]);
768 err_code |= ERR_ALERT | ERR_FATAL;
769 goto out;
770 }
771 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200772#endif
Remi Gacogne47783ef2015-05-29 15:53:22 +0200773#endif
Willy Tarreau33cb0652014-12-23 22:52:37 +0100774 else if (!strcmp(args[0], "tune.buffers.limit")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200775 if (alertif_too_many_args(1, file, linenum, args, &err_code))
776 goto out;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100777 if (*(args[1]) == 0) {
778 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
779 err_code |= ERR_ALERT | ERR_FATAL;
780 goto out;
781 }
782 global.tune.buf_limit = atol(args[1]);
783 if (global.tune.buf_limit) {
784 if (global.tune.buf_limit < 3)
785 global.tune.buf_limit = 3;
786 if (global.tune.buf_limit <= global.tune.reserved_bufs)
787 global.tune.buf_limit = global.tune.reserved_bufs + 1;
788 }
789 }
Willy Tarreau1058ae72014-12-23 22:40:40 +0100790 else if (!strcmp(args[0], "tune.buffers.reserve")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200791 if (alertif_too_many_args(1, file, linenum, args, &err_code))
792 goto out;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100793 if (*(args[1]) == 0) {
794 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
795 err_code |= ERR_ALERT | ERR_FATAL;
796 goto out;
797 }
798 global.tune.reserved_bufs = atol(args[1]);
799 if (global.tune.reserved_bufs < 2)
800 global.tune.reserved_bufs = 2;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100801 if (global.tune.buf_limit && global.tune.buf_limit <= global.tune.reserved_bufs)
802 global.tune.buf_limit = global.tune.reserved_bufs + 1;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100803 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200804 else if (!strcmp(args[0], "tune.bufsize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200805 if (alertif_too_many_args(1, file, linenum, args, &err_code))
806 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200807 if (*(args[1]) == 0) {
808 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
809 err_code |= ERR_ALERT | ERR_FATAL;
810 goto out;
811 }
812 global.tune.bufsize = atol(args[1]);
813 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
814 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100815 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100816 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200817 }
818 else if (!strcmp(args[0], "tune.maxrewrite")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200819 if (alertif_too_many_args(1, file, linenum, args, &err_code))
820 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200821 if (*(args[1]) == 0) {
822 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
823 err_code |= ERR_ALERT | ERR_FATAL;
824 goto out;
825 }
826 global.tune.maxrewrite = atol(args[1]);
827 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
828 global.tune.maxrewrite = global.tune.bufsize / 2;
829 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100830 else if (!strcmp(args[0], "tune.idletimer")) {
831 unsigned int idle;
832 const char *res;
833
William Lallemand1a748ae2015-05-19 16:37:23 +0200834 if (alertif_too_many_args(1, file, linenum, args, &err_code))
835 goto out;
Willy Tarreau7e312732014-02-12 16:35:14 +0100836 if (*(args[1]) == 0) {
837 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
838 err_code |= ERR_ALERT | ERR_FATAL;
839 goto out;
840 }
841
842 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
843 if (res) {
844 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
845 file, linenum, *res, args[0]);
846 err_code |= ERR_ALERT | ERR_FATAL;
847 goto out;
848 }
849
850 if (idle > 65535) {
851 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
852 err_code |= ERR_ALERT | ERR_FATAL;
853 goto out;
854 }
855 global.tune.idle_timer = idle;
856 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100857 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200858 if (alertif_too_many_args(1, file, linenum, args, &err_code))
859 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100860 if (global.tune.client_rcvbuf != 0) {
861 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
862 err_code |= ERR_ALERT;
863 goto out;
864 }
865 if (*(args[1]) == 0) {
866 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
867 err_code |= ERR_ALERT | ERR_FATAL;
868 goto out;
869 }
870 global.tune.client_rcvbuf = atol(args[1]);
871 }
872 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200873 if (alertif_too_many_args(1, file, linenum, args, &err_code))
874 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100875 if (global.tune.server_rcvbuf != 0) {
876 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
877 err_code |= ERR_ALERT;
878 goto out;
879 }
880 if (*(args[1]) == 0) {
881 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
882 err_code |= ERR_ALERT | ERR_FATAL;
883 goto out;
884 }
885 global.tune.server_rcvbuf = atol(args[1]);
886 }
887 else if (!strcmp(args[0], "tune.sndbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200888 if (alertif_too_many_args(1, file, linenum, args, &err_code))
889 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100890 if (global.tune.client_sndbuf != 0) {
891 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
892 err_code |= ERR_ALERT;
893 goto out;
894 }
895 if (*(args[1]) == 0) {
896 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
897 err_code |= ERR_ALERT | ERR_FATAL;
898 goto out;
899 }
900 global.tune.client_sndbuf = atol(args[1]);
901 }
902 else if (!strcmp(args[0], "tune.sndbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200903 if (alertif_too_many_args(1, file, linenum, args, &err_code))
904 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100905 if (global.tune.server_sndbuf != 0) {
906 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
907 err_code |= ERR_ALERT;
908 goto out;
909 }
910 if (*(args[1]) == 0) {
911 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
912 err_code |= ERR_ALERT | ERR_FATAL;
913 goto out;
914 }
915 global.tune.server_sndbuf = atol(args[1]);
916 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200917 else if (!strcmp(args[0], "tune.pipesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200918 if (alertif_too_many_args(1, file, linenum, args, &err_code))
919 goto out;
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200920 if (*(args[1]) == 0) {
921 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
922 err_code |= ERR_ALERT | ERR_FATAL;
923 goto out;
924 }
925 global.tune.pipesize = atol(args[1]);
926 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100927 else if (!strcmp(args[0], "tune.http.cookielen")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200928 if (alertif_too_many_args(1, file, linenum, args, &err_code))
929 goto out;
Willy Tarreau193b8c62012-11-22 00:17:38 +0100930 if (*(args[1]) == 0) {
931 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
932 err_code |= ERR_ALERT | ERR_FATAL;
933 goto out;
934 }
935 global.tune.cookie_len = atol(args[1]) + 1;
936 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200937 else if (!strcmp(args[0], "tune.http.maxhdr")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200938 if (alertif_too_many_args(1, file, linenum, args, &err_code))
939 goto out;
Willy Tarreauac1932d2011-10-24 19:14:41 +0200940 if (*(args[1]) == 0) {
941 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
942 err_code |= ERR_ALERT | ERR_FATAL;
943 goto out;
944 }
945 global.tune.max_http_hdr = atol(args[1]);
946 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100947 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
948#ifdef USE_ZLIB
William Lallemand1a748ae2015-05-19 16:37:23 +0200949 if (alertif_too_many_args(1, file, linenum, args, &err_code))
950 goto out;
William Lallemanda509e4c2012-11-07 16:54:34 +0100951 if (*args[1]) {
952 global.tune.zlibmemlevel = atoi(args[1]);
953 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
954 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
955 file, linenum, args[0]);
956 err_code |= ERR_ALERT | ERR_FATAL;
957 goto out;
958 }
959 } else {
960 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
961 file, linenum, args[0]);
962 err_code |= ERR_ALERT | ERR_FATAL;
963 goto out;
964 }
965#else
966 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
967 err_code |= ERR_ALERT | ERR_FATAL;
968 goto out;
969#endif
970 }
971 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
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.zlibwindowsize = atoi(args[1]);
977 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
978 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\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 8 and 15\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 }
William Lallemandf3747832012-11-09 12:33:10 +0100995 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200996 if (alertif_too_many_args(1, file, linenum, args, &err_code))
997 goto out;
William Lallemandf3747832012-11-09 12:33:10 +0100998 if (*args[1]) {
999 global.tune.comp_maxlevel = atoi(args[1]);
1000 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
1001 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1002 file, linenum, args[0]);
1003 err_code |= ERR_ALERT | ERR_FATAL;
1004 goto out;
1005 }
1006 } else {
1007 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1008 file, linenum, args[0]);
1009 err_code |= ERR_ALERT | ERR_FATAL;
1010 goto out;
1011 }
1012 }
Willy Tarreauf3045d22015-04-29 16:24:50 +02001013 else if (!strcmp(args[0], "tune.pattern.cache-size")) {
1014 if (*args[1]) {
1015 global.tune.pattern_cache = atoi(args[1]);
1016 if (global.tune.pattern_cache < 0) {
1017 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
1018 file, linenum, args[0]);
1019 err_code |= ERR_ALERT | ERR_FATAL;
1020 goto out;
1021 }
1022 } else {
1023 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
1024 file, linenum, args[0]);
1025 err_code |= ERR_ALERT | ERR_FATAL;
1026 goto out;
1027 }
1028 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001029 else if (!strcmp(args[0], "uid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001030 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1031 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001032 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001033 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001034 err_code |= ERR_ALERT;
1035 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001036 }
1037 if (*(args[1]) == 0) {
1038 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001039 err_code |= ERR_ALERT | ERR_FATAL;
1040 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001041 }
1042 global.uid = atol(args[1]);
1043 }
1044 else if (!strcmp(args[0], "gid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001045 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1046 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001047 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001048 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001049 err_code |= ERR_ALERT;
1050 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001051 }
1052 if (*(args[1]) == 0) {
1053 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001054 err_code |= ERR_ALERT | ERR_FATAL;
1055 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001056 }
1057 global.gid = atol(args[1]);
1058 }
Simon Horman98637e52014-06-20 12:30:16 +09001059 else if (!strcmp(args[0], "external-check")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001060 if (alertif_too_many_args(0, file, linenum, args, &err_code))
1061 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09001062 global.external_check = 1;
1063 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001064 /* user/group name handling */
1065 else if (!strcmp(args[0], "user")) {
1066 struct passwd *ha_user;
William Lallemand1a748ae2015-05-19 16:37:23 +02001067 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1068 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001069 if (global.uid != 0) {
1070 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001071 err_code |= ERR_ALERT;
1072 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001073 }
1074 errno = 0;
1075 ha_user = getpwnam(args[1]);
1076 if (ha_user != NULL) {
1077 global.uid = (int)ha_user->pw_uid;
1078 }
1079 else {
1080 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 +02001081 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001082 }
1083 }
1084 else if (!strcmp(args[0], "group")) {
1085 struct group *ha_group;
William Lallemand1a748ae2015-05-19 16:37:23 +02001086 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1087 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001088 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02001089 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001090 err_code |= ERR_ALERT;
1091 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001092 }
1093 errno = 0;
1094 ha_group = getgrnam(args[1]);
1095 if (ha_group != NULL) {
1096 global.gid = (int)ha_group->gr_gid;
1097 }
1098 else {
1099 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 +02001100 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001101 }
1102 }
1103 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +02001104 else if (!strcmp(args[0], "nbproc")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001105 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1106 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001107 if (*(args[1]) == 0) {
1108 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001109 err_code |= ERR_ALERT | ERR_FATAL;
1110 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001111 }
1112 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001113 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
1114 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
1115 file, linenum, args[0], LONGBITS, global.nbproc);
1116 err_code |= ERR_ALERT | ERR_FATAL;
1117 goto out;
1118 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001119 }
1120 else if (!strcmp(args[0], "maxconn")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001121 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1122 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001123 if (global.maxconn != 0) {
1124 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001125 err_code |= ERR_ALERT;
1126 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001127 }
1128 if (*(args[1]) == 0) {
1129 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001130 err_code |= ERR_ALERT | ERR_FATAL;
1131 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001132 }
1133 global.maxconn = atol(args[1]);
1134#ifdef SYSTEM_MAXCONN
1135 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
1136 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);
1137 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +02001138 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001139 }
1140#endif /* SYSTEM_MAXCONN */
1141 }
Willy Tarreau403edff2012-09-06 11:58:37 +02001142 else if (!strcmp(args[0], "maxsslconn")) {
1143#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001144 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1145 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001146 if (*(args[1]) == 0) {
1147 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1148 err_code |= ERR_ALERT | ERR_FATAL;
1149 goto out;
1150 }
1151 global.maxsslconn = atol(args[1]);
1152#else
Emeric Brun0914df82012-10-02 18:45:42 +02001153 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1154 err_code |= ERR_ALERT | ERR_FATAL;
1155 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001156#endif
1157 }
Willy Tarreau610f04b2014-02-13 11:36:41 +01001158 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
1159#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001160 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1161 goto out;
Willy Tarreau610f04b2014-02-13 11:36:41 +01001162 if (*(args[1]) == 0) {
1163 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1164 err_code |= ERR_ALERT | ERR_FATAL;
1165 goto out;
1166 }
1167 free(global.listen_default_ciphers);
1168 global.listen_default_ciphers = strdup(args[1]);
1169#else
1170 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1171 err_code |= ERR_ALERT | ERR_FATAL;
1172 goto out;
1173#endif
1174 }
1175 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
1176#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001177 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1178 goto out;
Willy Tarreau610f04b2014-02-13 11:36:41 +01001179 if (*(args[1]) == 0) {
1180 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1181 err_code |= ERR_ALERT | ERR_FATAL;
1182 goto out;
1183 }
1184 free(global.connect_default_ciphers);
1185 global.connect_default_ciphers = strdup(args[1]);
1186#else
1187 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1188 err_code |= ERR_ALERT | ERR_FATAL;
1189 goto out;
1190#endif
1191 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02001192#ifdef USE_OPENSSL
1193#ifndef OPENSSL_NO_DH
1194 else if (!strcmp(args[0], "ssl-dh-param-file")) {
1195 if (*(args[1]) == 0) {
1196 Alert("parsing [%s:%d] : '%s' expects a file path as an argument.\n", file, linenum, args[0]);
1197 err_code |= ERR_ALERT | ERR_FATAL;
1198 goto out;
1199 }
1200 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
1201 Alert("parsing [%s:%d] : '%s': unable to load DH parameters from file <%s>.\n", file, linenum, args[0], args[1]);
1202 err_code |= ERR_ALERT | ERR_FATAL;
1203 goto out;
1204 }
1205 }
1206#endif
1207#endif
Emeric Brun850efd52014-01-29 12:24:34 +01001208 else if (!strcmp(args[0], "ssl-server-verify")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001209 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1210 goto out;
Emeric Brun850efd52014-01-29 12:24:34 +01001211 if (*(args[1]) == 0) {
1212 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1213 err_code |= ERR_ALERT | ERR_FATAL;
1214 goto out;
1215 }
1216 if (strcmp(args[1],"none") == 0)
1217 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1218 else if (strcmp(args[1],"required") == 0)
1219 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1220 else {
1221 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1222 err_code |= ERR_ALERT | ERR_FATAL;
1223 goto out;
1224 }
1225 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001226 else if (!strcmp(args[0], "maxconnrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001227 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1228 goto out;
Willy Tarreau81c25d02011-09-07 15:17:21 +02001229 if (global.cps_lim != 0) {
1230 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1231 err_code |= ERR_ALERT;
1232 goto out;
1233 }
1234 if (*(args[1]) == 0) {
1235 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1236 err_code |= ERR_ALERT | ERR_FATAL;
1237 goto out;
1238 }
1239 global.cps_lim = atol(args[1]);
1240 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001241 else if (!strcmp(args[0], "maxsessrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001242 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1243 goto out;
Willy Tarreau93e7c002013-10-07 18:51:07 +02001244 if (global.sps_lim != 0) {
1245 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1246 err_code |= ERR_ALERT;
1247 goto out;
1248 }
1249 if (*(args[1]) == 0) {
1250 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1251 err_code |= ERR_ALERT | ERR_FATAL;
1252 goto out;
1253 }
1254 global.sps_lim = atol(args[1]);
1255 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001256 else if (!strcmp(args[0], "maxsslrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001257 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1258 goto out;
Willy Tarreaue43d5322013-10-07 20:01:52 +02001259 if (global.ssl_lim != 0) {
1260 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1261 err_code |= ERR_ALERT;
1262 goto out;
1263 }
1264 if (*(args[1]) == 0) {
1265 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1266 err_code |= ERR_ALERT | ERR_FATAL;
1267 goto out;
1268 }
1269 global.ssl_lim = atol(args[1]);
1270 }
William Lallemandd85f9172012-11-09 17:05:39 +01001271 else if (!strcmp(args[0], "maxcomprate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001272 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1273 goto out;
William Lallemandd85f9172012-11-09 17:05:39 +01001274 if (*(args[1]) == 0) {
1275 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1276 err_code |= ERR_ALERT | ERR_FATAL;
1277 goto out;
1278 }
1279 global.comp_rate_lim = atoi(args[1]) * 1024;
1280 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001281 else if (!strcmp(args[0], "maxpipes")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001282 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1283 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001284 if (global.maxpipes != 0) {
1285 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001286 err_code |= ERR_ALERT;
1287 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001288 }
1289 if (*(args[1]) == 0) {
1290 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001291 err_code |= ERR_ALERT | ERR_FATAL;
1292 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001293 }
1294 global.maxpipes = atol(args[1]);
1295 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001296 else if (!strcmp(args[0], "maxzlibmem")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001297 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1298 goto out;
William Lallemand9d5f5482012-11-07 16:12:57 +01001299 if (*(args[1]) == 0) {
1300 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1301 err_code |= ERR_ALERT | ERR_FATAL;
1302 goto out;
1303 }
William Lallemande3a7d992012-11-20 11:25:20 +01001304 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001305 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001306 else if (!strcmp(args[0], "maxcompcpuusage")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001307 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1308 goto out;
William Lallemand072a2bf2012-11-20 17:01:01 +01001309 if (*(args[1]) == 0) {
1310 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1311 err_code |= ERR_ALERT | ERR_FATAL;
1312 goto out;
1313 }
1314 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001315 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001316 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1317 err_code |= ERR_ALERT | ERR_FATAL;
1318 goto out;
1319 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001320 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001321
Willy Tarreaubaaee002006-06-26 02:48:02 +02001322 else if (!strcmp(args[0], "ulimit-n")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001323 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1324 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001325 if (global.rlimit_nofile != 0) {
1326 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001327 err_code |= ERR_ALERT;
1328 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001329 }
1330 if (*(args[1]) == 0) {
1331 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001332 err_code |= ERR_ALERT | ERR_FATAL;
1333 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001334 }
1335 global.rlimit_nofile = atol(args[1]);
1336 }
1337 else if (!strcmp(args[0], "chroot")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001338 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1339 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001340 if (global.chroot != NULL) {
1341 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001342 err_code |= ERR_ALERT;
1343 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001344 }
1345 if (*(args[1]) == 0) {
1346 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001347 err_code |= ERR_ALERT | ERR_FATAL;
1348 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001349 }
1350 global.chroot = strdup(args[1]);
1351 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001352 else if (!strcmp(args[0], "description")) {
1353 int i, len=0;
1354 char *d;
1355
1356 if (!*args[1]) {
1357 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1358 file, linenum, args[0]);
1359 err_code |= ERR_ALERT | ERR_FATAL;
1360 goto out;
1361 }
1362
Willy Tarreau348acfe2014-04-14 15:00:39 +02001363 for (i = 1; *args[i]; i++)
1364 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001365
1366 if (global.desc)
1367 free(global.desc);
1368
1369 global.desc = d = (char *)calloc(1, len);
1370
Willy Tarreau348acfe2014-04-14 15:00:39 +02001371 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1372 for (i = 2; *args[i]; i++)
1373 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001374 }
1375 else if (!strcmp(args[0], "node")) {
1376 int i;
1377 char c;
1378
William Lallemand1a748ae2015-05-19 16:37:23 +02001379 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1380 goto out;
1381
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001382 for (i=0; args[1][i]; i++) {
1383 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001384 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1385 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001386 break;
1387 }
1388
1389 if (!i || args[1][i]) {
1390 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1391 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1392 file, linenum, args[0]);
1393 err_code |= ERR_ALERT | ERR_FATAL;
1394 goto out;
1395 }
1396
1397 if (global.node)
1398 free(global.node);
1399
1400 global.node = strdup(args[1]);
1401 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001402 else if (!strcmp(args[0], "pidfile")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001403 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1404 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001405 if (global.pidfile != NULL) {
1406 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001407 err_code |= ERR_ALERT;
1408 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001409 }
1410 if (*(args[1]) == 0) {
1411 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001412 err_code |= ERR_ALERT | ERR_FATAL;
1413 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001414 }
1415 global.pidfile = strdup(args[1]);
1416 }
Emeric Bruned760922010-10-22 17:59:25 +02001417 else if (!strcmp(args[0], "unix-bind")) {
1418 int cur_arg = 1;
1419 while (*(args[cur_arg])) {
1420 if (!strcmp(args[cur_arg], "prefix")) {
1421 if (global.unix_bind.prefix != NULL) {
1422 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1423 err_code |= ERR_ALERT;
1424 cur_arg += 2;
1425 continue;
1426 }
1427
1428 if (*(args[cur_arg+1]) == 0) {
1429 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1430 err_code |= ERR_ALERT | ERR_FATAL;
1431 goto out;
1432 }
1433 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1434 cur_arg += 2;
1435 continue;
1436 }
1437
1438 if (!strcmp(args[cur_arg], "mode")) {
1439
1440 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1441 cur_arg += 2;
1442 continue;
1443 }
1444
1445 if (!strcmp(args[cur_arg], "uid")) {
1446
1447 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1448 cur_arg += 2;
1449 continue;
1450 }
1451
1452 if (!strcmp(args[cur_arg], "gid")) {
1453
1454 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1455 cur_arg += 2;
1456 continue;
1457 }
1458
1459 if (!strcmp(args[cur_arg], "user")) {
1460 struct passwd *user;
1461
1462 user = getpwnam(args[cur_arg + 1]);
1463 if (!user) {
1464 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1465 file, linenum, args[0], args[cur_arg + 1 ]);
1466 err_code |= ERR_ALERT | ERR_FATAL;
1467 goto out;
1468 }
1469
1470 global.unix_bind.ux.uid = user->pw_uid;
1471 cur_arg += 2;
1472 continue;
1473 }
1474
1475 if (!strcmp(args[cur_arg], "group")) {
1476 struct group *group;
1477
1478 group = getgrnam(args[cur_arg + 1]);
1479 if (!group) {
1480 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1481 file, linenum, args[0], args[cur_arg + 1 ]);
1482 err_code |= ERR_ALERT | ERR_FATAL;
1483 goto out;
1484 }
1485
1486 global.unix_bind.ux.gid = group->gr_gid;
1487 cur_arg += 2;
1488 continue;
1489 }
1490
Willy Tarreaub48f9582011-09-05 01:17:06 +02001491 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001492 file, linenum, args[0]);
1493 err_code |= ERR_ALERT | ERR_FATAL;
1494 goto out;
1495 }
1496 }
William Lallemand0f99e342011-10-12 17:50:54 +02001497 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1498 /* delete previous herited or defined syslog servers */
1499 struct logsrv *back;
1500 struct logsrv *tmp;
1501
1502 if (*(args[1]) != 0) {
1503 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1504 err_code |= ERR_ALERT | ERR_FATAL;
1505 goto out;
1506 }
1507
1508 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1509 LIST_DEL(&tmp->list);
1510 free(tmp);
1511 }
1512 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001513 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001514 struct sockaddr_storage *sk;
1515 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001516 struct logsrv *logsrv;
Willy Tarreau18324f52014-06-27 18:10:07 +02001517 int arg = 0;
1518 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001519
William Lallemand1a748ae2015-05-19 16:37:23 +02001520 if (alertif_too_many_args(8, file, linenum, args, &err_code)) /* does not strictly check optional arguments */
1521 goto out;
1522
Willy Tarreaubaaee002006-06-26 02:48:02 +02001523 if (*(args[1]) == 0 || *(args[2]) == 0) {
1524 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001525 err_code |= ERR_ALERT | ERR_FATAL;
1526 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001527 }
William Lallemand0f99e342011-10-12 17:50:54 +02001528
1529 logsrv = calloc(1, sizeof(struct logsrv));
1530
Willy Tarreau18324f52014-06-27 18:10:07 +02001531 /* just after the address, a length may be specified */
1532 if (strcmp(args[arg+2], "len") == 0) {
1533 len = atoi(args[arg+3]);
1534 if (len < 80 || len > 65535) {
1535 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1536 file, linenum, args[arg+3]);
1537 err_code |= ERR_ALERT | ERR_FATAL;
1538 goto out;
1539 }
1540 logsrv->maxlen = len;
1541
1542 /* skip these two args */
1543 arg += 2;
1544 }
1545 else
1546 logsrv->maxlen = MAX_SYSLOG_LEN;
1547
1548 if (logsrv->maxlen > global.max_syslog_len) {
1549 global.max_syslog_len = logsrv->maxlen;
1550 logline = realloc(logline, global.max_syslog_len + 1);
1551 }
1552
William Lallemand1a748ae2015-05-19 16:37:23 +02001553 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
1554 goto out;
1555
Willy Tarreau18324f52014-06-27 18:10:07 +02001556 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001557 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001558 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001559 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001560 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001561 }
1562
William Lallemand0f99e342011-10-12 17:50:54 +02001563 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02001564 if (*(args[arg+3])) {
1565 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001566 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001567 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001568 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001569 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001570 }
1571 }
1572
William Lallemand0f99e342011-10-12 17:50:54 +02001573 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02001574 if (*(args[arg+4])) {
1575 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001576 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001577 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001578 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001579 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001580 }
1581 }
1582
Willy Tarreau902636f2013-03-10 19:44:48 +01001583 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001584 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001585 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001586 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001587 free(logsrv);
1588 goto out;
1589 }
1590 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001591
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001592 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001593 if (port1 != port2) {
1594 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1595 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001596 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001597 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001598 goto out;
1599 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001600
William Lallemand0f99e342011-10-12 17:50:54 +02001601 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001602 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001603 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001604 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001605
William Lallemand0f99e342011-10-12 17:50:54 +02001606 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001607 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001608 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1609 char *name;
1610 int len;
1611
1612 if (global.log_send_hostname != NULL) {
1613 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1614 err_code |= ERR_ALERT;
1615 goto out;
1616 }
1617
1618 if (*(args[1]))
1619 name = args[1];
1620 else
1621 name = hostname;
1622
1623 len = strlen(name);
1624
1625 /* We'll add a space after the name to respect the log format */
1626 free(global.log_send_hostname);
1627 global.log_send_hostname = malloc(len + 2);
1628 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1629 }
Kevinm48936af2010-12-22 16:08:21 +00001630 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
William Lallemand1a748ae2015-05-19 16:37:23 +02001631 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1632 goto out;
Kevinm48936af2010-12-22 16:08:21 +00001633 if (*(args[1]) == 0) {
1634 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1635 err_code |= ERR_ALERT | ERR_FATAL;
1636 goto out;
1637 }
1638 free(global.log_tag);
1639 global.log_tag = strdup(args[1]);
1640 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001641 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
William Lallemand1a748ae2015-05-19 16:37:23 +02001642 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1643 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001644 if (global.spread_checks != 0) {
1645 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001646 err_code |= ERR_ALERT;
1647 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001648 }
1649 if (*(args[1]) == 0) {
1650 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001651 err_code |= ERR_ALERT | ERR_FATAL;
1652 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001653 }
1654 global.spread_checks = atol(args[1]);
1655 if (global.spread_checks < 0 || global.spread_checks > 50) {
1656 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001657 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001658 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001659 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001660 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1661 const char *err;
1662 unsigned int val;
1663
William Lallemand1a748ae2015-05-19 16:37:23 +02001664 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1665 goto out;
Willy Tarreau1746eec2014-04-25 10:46:47 +02001666 if (*(args[1]) == 0) {
1667 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1668 err_code |= ERR_ALERT | ERR_FATAL;
1669 goto out;
1670 }
1671
1672 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1673 if (err) {
1674 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1675 err_code |= ERR_ALERT | ERR_FATAL;
1676 }
1677 global.max_spread_checks = val;
1678 if (global.max_spread_checks < 0) {
1679 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1680 err_code |= ERR_ALERT | ERR_FATAL;
1681 }
1682 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001683 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1684#ifdef USE_CPU_AFFINITY
1685 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001686 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001687 unsigned long cpus = 0;
1688
1689 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001690 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001691 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001692 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001693 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001694 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001695 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001696 proc = atol(args[1]);
1697 if (proc >= 1 && proc <= LONGBITS)
1698 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001699 }
1700
1701 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001702 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",
1703 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001704 err_code |= ERR_ALERT | ERR_FATAL;
1705 goto out;
1706 }
1707
1708 cur_arg = 2;
1709 while (*args[cur_arg]) {
1710 unsigned int low, high;
1711
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001712 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001713 char *dash = strchr(args[cur_arg], '-');
1714
1715 low = high = str2uic(args[cur_arg]);
1716 if (dash)
1717 high = str2uic(dash + 1);
1718
1719 if (high < low) {
1720 unsigned int swap = low;
1721 low = high;
1722 high = swap;
1723 }
1724
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001725 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001726 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001727 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001728 err_code |= ERR_ALERT | ERR_FATAL;
1729 goto out;
1730 }
1731
1732 while (low <= high)
1733 cpus |= 1UL << low++;
1734 }
1735 else {
1736 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1737 file, linenum, args[0], args[cur_arg]);
1738 err_code |= ERR_ALERT | ERR_FATAL;
1739 goto out;
1740 }
1741 cur_arg++;
1742 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001743 for (i = 0; i < LONGBITS; i++)
1744 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001745 global.cpu_map[i] = cpus;
1746#else
1747 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1748 err_code |= ERR_ALERT | ERR_FATAL;
1749 goto out;
1750#endif
1751 }
Thomas Holmes0809f262015-05-12 15:50:47 +01001752#ifdef USE_51DEGREES
1753 else if (strcmp(args[0], "51degrees-data-file") == 0) {
1754 if(!*(args[1])) {
1755 Alert("parsing [%s:%d]: '%s' expects a filepath to a 51Degrees data file.\n", file, linenum, args[0]);
1756 err_code |= ERR_ALERT | ERR_FATAL;
1757 goto out;
1758 }
1759 global._51d_data_file_path = strdup(args[1]);
1760 }
1761 else if (strcmp(args[0], "51degrees-property-seperator") == 0) {
1762 if(!*(args[1])) {
1763 Alert("parsing [%s:%d]: '%s' expects a ingle character.\n", file, linenum, args[0]);
1764 err_code |= ERR_ALERT | ERR_FATAL;
1765 goto out;
1766 }
1767 if (strlen(args[1]) > 1) {
1768 Alert("parsing [%s:%d]: '%s' expects a ingle character, got '%s'.\n", file, linenum, args[0], args[1]);
1769 err_code |= ERR_ALERT | ERR_FATAL;
1770 goto out;
1771 }
1772 global._51d_property_seperator = *args[1];
1773 }
1774 else if (strcmp(args[0], "51degrees-property-name-list") == 0) {
1775 int arg;
1776 struct _51d_property_names *name;
1777
1778 arg = 1;
1779 if (!*args[arg]) {
1780 Alert("parsing [%s:%d]: '%s' expects at least one 51Degrees property name.\n", file, linenum, args[0]);
1781 err_code |= ERR_ALERT | ERR_FATAL;
1782 goto out;
1783 }
1784
1785 LIST_INIT(&global._51d_property_names);
1786 while (*args[arg]) {
1787 name = calloc(1, sizeof(struct _51d_property_names));
1788 name->name = strdup(args[arg]);
1789 LIST_ADDQ(&global._51d_property_names, &name->list);
1790 ++arg;
1791 }
1792 }
1793#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001794 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001795 struct cfg_kw_list *kwl;
1796 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001797 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001798
1799 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1800 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1801 if (kwl->kw[index].section != CFG_GLOBAL)
1802 continue;
1803 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001804 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001805 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001806 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001807 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001808 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001809 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001810 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001811 err_code |= ERR_WARN;
1812 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001813 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001814 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001815 }
1816 }
1817 }
1818
Willy Tarreaubaaee002006-06-26 02:48:02 +02001819 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001820 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001821 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001822
Willy Tarreau058e9072009-07-20 09:30:05 +02001823 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001824 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001825 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001826}
1827
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001828void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001829{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001830 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001831 defproxy.mode = PR_MODE_TCP;
1832 defproxy.state = PR_STNEW;
1833 defproxy.maxconn = cfg_maxpconn;
1834 defproxy.conn_retries = CONN_RETRIES;
Joseph Lynch726ab712015-05-11 23:25:34 -07001835 defproxy.redispatch_after = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001836
Simon Horman66183002013-02-23 10:16:43 +09001837 defproxy.defsrv.check.inter = DEF_CHKINTR;
1838 defproxy.defsrv.check.fastinter = 0;
1839 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001840 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1841 defproxy.defsrv.agent.fastinter = 0;
1842 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001843 defproxy.defsrv.check.rise = DEF_RISETIME;
1844 defproxy.defsrv.check.fall = DEF_FALLTIME;
1845 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1846 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001847 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001848 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001849 defproxy.defsrv.maxqueue = 0;
1850 defproxy.defsrv.minconn = 0;
1851 defproxy.defsrv.maxconn = 0;
1852 defproxy.defsrv.slowstart = 0;
1853 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1854 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1855 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Simon Horman64e34162015-02-06 11:11:57 +09001856
1857 defproxy.email_alert.level = LOG_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001858}
1859
Willy Tarreauade5ec42010-01-28 19:33:49 +01001860
Willy Tarreau63af98d2014-05-18 08:11:41 +02001861/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1862 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1863 * ERR_FATAL in case of error.
1864 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001865static int create_cond_regex_rule(const char *file, int line,
1866 struct proxy *px, int dir, int action, int flags,
1867 const char *cmd, const char *reg, const char *repl,
1868 const char **cond_start)
1869{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001870 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001871 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001872 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001873 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001874 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001875 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001876 int cs;
1877 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001878
1879 if (px == &defproxy) {
1880 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001881 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001882 goto err;
1883 }
1884
1885 if (*reg == 0) {
1886 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001887 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001888 goto err;
1889 }
1890
1891 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001892 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001893
Willy Tarreau5321c422010-01-28 20:35:13 +01001894 if (cond_start &&
1895 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001896 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1897 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1898 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001899 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001900 goto err;
1901 }
1902 }
1903 else if (cond_start && **cond_start) {
1904 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1905 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001906 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001907 goto err;
1908 }
1909
Willy Tarreau63af98d2014-05-18 08:11:41 +02001910 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001911 (dir == SMP_OPT_DIR_REQ) ?
1912 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1913 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1914 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001915
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001916 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001917 if (!preg) {
1918 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001919 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001920 goto err;
1921 }
1922
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001923 cs = !(flags & REG_ICASE);
1924 cap = !(flags & REG_NOSUB);
1925 error = NULL;
1926 if (!regex_comp(reg, preg, cs, cap, &error)) {
1927 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1928 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001929 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001930 goto err;
1931 }
1932
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001933 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001934 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001935 if (repl && err) {
1936 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1937 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001938 ret_code |= ERR_ALERT | ERR_FATAL;
1939 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001940 }
1941
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001942 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001943 ret_code |= ERR_WARN;
1944
1945 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001946
Willy Tarreau63af98d2014-05-18 08:11:41 +02001947 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001948 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001949 err:
1950 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001951 free(errmsg);
1952 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001953}
1954
Willy Tarreaubaaee002006-06-26 02:48:02 +02001955/*
William Lallemand51097192015-04-14 16:35:22 +02001956 * Parse a line in a <listen>, <frontend> or <backend> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001957 * Returns the error code, 0 if OK, or any combination of :
1958 * - ERR_ABORT: must abort ASAP
1959 * - ERR_FATAL: we can continue parsing but not start the service
1960 * - ERR_WARN: a warning has been emitted
1961 * - ERR_ALERT: an alert has been emitted
1962 * Only the two first ones can stop processing, the two others are just
1963 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001964 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001965int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1966{
1967 static struct peers *curpeers = NULL;
1968 struct peer *newpeer = NULL;
1969 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001970 struct bind_conf *bind_conf;
1971 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001972 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001973 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001974
1975 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001976 if (!*args[1]) {
1977 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001978 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001979 goto out;
1980 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001981
William Lallemand6e62fb62015-04-28 16:55:23 +02001982 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1983 goto out;
1984
Emeric Brun32da3c42010-09-23 18:39:19 +02001985 err = invalid_char(args[1]);
1986 if (err) {
1987 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1988 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001989 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001990 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001991 }
1992
1993 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1994 /*
1995 * If there are two proxies with the same name only following
1996 * combinations are allowed:
1997 */
1998 if (strcmp(curpeers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02001999 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 +02002000 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002001 err_code |= ERR_ALERT | ERR_FATAL;
Emeric Brun32da3c42010-09-23 18:39:19 +02002002 }
2003 }
2004
2005 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
2006 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2007 err_code |= ERR_ALERT | ERR_ABORT;
2008 goto out;
2009 }
2010
2011 curpeers->next = peers;
2012 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002013 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002014 curpeers->conf.line = linenum;
2015 curpeers->last_change = now.tv_sec;
2016 curpeers->id = strdup(args[1]);
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002017 curpeers->state = PR_STNEW;
Emeric Brun32da3c42010-09-23 18:39:19 +02002018 }
2019 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01002020 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01002021 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002022 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02002023
2024 if (!*args[2]) {
2025 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2026 file, linenum, args[0]);
2027 err_code |= ERR_ALERT | ERR_FATAL;
2028 goto out;
2029 }
2030
2031 err = invalid_char(args[1]);
2032 if (err) {
2033 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2034 file, linenum, *err, args[1]);
2035 err_code |= ERR_ALERT | ERR_FATAL;
2036 goto out;
2037 }
2038
2039 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
2040 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2041 err_code |= ERR_ALERT | ERR_ABORT;
2042 goto out;
2043 }
2044
2045 /* the peers are linked backwards first */
2046 curpeers->count++;
2047 newpeer->next = curpeers->remote;
2048 curpeers->remote = newpeer;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002049 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002050 newpeer->conf.line = linenum;
2051
2052 newpeer->last_change = now.tv_sec;
2053 newpeer->id = strdup(args[1]);
2054
Willy Tarreau902636f2013-03-10 19:44:48 +01002055 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002056 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01002057 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002058 err_code |= ERR_ALERT | ERR_FATAL;
2059 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002060 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01002061
2062 proto = protocol_by_family(sk->ss_family);
2063 if (!proto || !proto->connect) {
2064 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2065 file, linenum, args[0], args[1]);
2066 err_code |= ERR_ALERT | ERR_FATAL;
2067 goto out;
2068 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002069
2070 if (port1 != port2) {
2071 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2072 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002073 err_code |= ERR_ALERT | ERR_FATAL;
2074 goto out;
2075 }
2076
Willy Tarreau2aa38802013-02-20 19:20:59 +01002077 if (!port1) {
2078 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2079 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002080 err_code |= ERR_ALERT | ERR_FATAL;
2081 goto out;
2082 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002083
Emeric Brun32da3c42010-09-23 18:39:19 +02002084 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002085 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002086 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02002087 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02002088
Emeric Brun32da3c42010-09-23 18:39:19 +02002089 if (strcmp(newpeer->id, localpeer) == 0) {
2090 /* Current is local peer, it define a frontend */
2091 newpeer->local = 1;
Emeric Brunb3971ab2015-05-12 18:49:09 +02002092 peers->local = newpeer;
Emeric Brun32da3c42010-09-23 18:39:19 +02002093
2094 if (!curpeers->peers_fe) {
2095 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
2096 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2097 err_code |= ERR_ALERT | ERR_ABORT;
2098 goto out;
2099 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002100
Willy Tarreau237250c2011-07-29 01:49:03 +02002101 init_new_proxy(curpeers->peers_fe);
2102 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02002103 curpeers->peers_fe->id = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002104 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
2105 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau91d96282015-03-13 15:47:26 +01002106 peers_setup_frontend(curpeers->peers_fe);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002107
2108 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
2109
Willy Tarreau902636f2013-03-10 19:44:48 +01002110 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
2111 if (errmsg && *errmsg) {
2112 indent_msg(&errmsg, 2);
2113 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002114 }
2115 else
2116 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
2117 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002118 err_code |= ERR_FATAL;
2119 goto out;
2120 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02002121
2122 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01002123 l->maxaccept = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002124 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
2125 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
Willy Tarreau9903f0e2015-04-04 18:50:31 +02002126 l->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02002127 l->handler = process_stream;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002128 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01002129 l->default_target = ((struct proxy *)curpeers->peers_fe)->default_target;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002130 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
2131 global.maxsock += l->maxconn;
2132 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002133 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01002134 else {
2135 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
2136 file, linenum, args[0], args[1],
2137 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
2138 err_code |= ERR_FATAL;
2139 goto out;
2140 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002141 }
2142 } /* neither "peer" nor "peers" */
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002143 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
2144 curpeers->state = PR_STSTOPPED;
2145 }
2146 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
2147 curpeers->state = PR_STNEW;
2148 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002149 else if (*args[0] != 0) {
2150 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2151 err_code |= ERR_ALERT | ERR_FATAL;
2152 goto out;
2153 }
2154
2155out:
Willy Tarreau902636f2013-03-10 19:44:48 +01002156 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02002157 return err_code;
2158}
2159
Simon Horman0d16a402015-01-30 11:22:58 +09002160
2161/*
William Lallemand51097192015-04-14 16:35:22 +02002162 * Parse a line in a <listen>, <frontend> or <backend> section.
Simon Horman0d16a402015-01-30 11:22:58 +09002163 * Returns the error code, 0 if OK, or any combination of :
2164 * - ERR_ABORT: must abort ASAP
2165 * - ERR_FATAL: we can continue parsing but not start the service
2166 * - ERR_WARN: a warning has been emitted
2167 * - ERR_ALERT: an alert has been emitted
2168 * Only the two first ones can stop processing, the two others are just
2169 * indicators.
2170 */
2171int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
2172{
2173 static struct mailers *curmailers = NULL;
2174 struct mailer *newmailer = NULL;
2175 const char *err;
2176 int err_code = 0;
2177 char *errmsg = NULL;
2178
2179 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
2180 if (!*args[1]) {
2181 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
2182 err_code |= ERR_ALERT | ERR_ABORT;
2183 goto out;
2184 }
2185
2186 err = invalid_char(args[1]);
2187 if (err) {
2188 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2189 file, linenum, *err, args[0], args[1]);
2190 err_code |= ERR_ALERT | ERR_ABORT;
2191 goto out;
2192 }
2193
2194 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
2195 /*
2196 * If there are two proxies with the same name only following
2197 * combinations are allowed:
2198 */
2199 if (strcmp(curmailers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002200 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 +09002201 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002202 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman0d16a402015-01-30 11:22:58 +09002203 }
2204 }
2205
2206 if ((curmailers = (struct mailers *)calloc(1, sizeof(struct mailers))) == NULL) {
2207 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2208 err_code |= ERR_ALERT | ERR_ABORT;
2209 goto out;
2210 }
2211
2212 curmailers->next = mailers;
2213 mailers = curmailers;
2214 curmailers->conf.file = strdup(file);
2215 curmailers->conf.line = linenum;
2216 curmailers->id = strdup(args[1]);
2217 }
2218 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
2219 struct sockaddr_storage *sk;
2220 int port1, port2;
2221 struct protocol *proto;
2222
2223 if (!*args[2]) {
2224 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2225 file, linenum, args[0]);
2226 err_code |= ERR_ALERT | ERR_FATAL;
2227 goto out;
2228 }
2229
2230 err = invalid_char(args[1]);
2231 if (err) {
2232 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2233 file, linenum, *err, args[1]);
2234 err_code |= ERR_ALERT | ERR_FATAL;
2235 goto out;
2236 }
2237
2238 if ((newmailer = (struct mailer *)calloc(1, sizeof(struct mailer))) == NULL) {
2239 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2240 err_code |= ERR_ALERT | ERR_ABORT;
2241 goto out;
2242 }
2243
2244 /* the mailers are linked backwards first */
2245 curmailers->count++;
2246 newmailer->next = curmailers->mailer_list;
2247 curmailers->mailer_list = newmailer;
2248 newmailer->mailers = curmailers;
2249 newmailer->conf.file = strdup(file);
2250 newmailer->conf.line = linenum;
2251
2252 newmailer->id = strdup(args[1]);
2253
2254 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
2255 if (!sk) {
2256 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2257 err_code |= ERR_ALERT | ERR_FATAL;
2258 goto out;
2259 }
2260
2261 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002262 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2263 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002264 file, linenum, args[0], args[1]);
2265 err_code |= ERR_ALERT | ERR_FATAL;
2266 goto out;
2267 }
2268
2269 if (port1 != port2) {
2270 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2271 file, linenum, args[0], args[1], args[2]);
2272 err_code |= ERR_ALERT | ERR_FATAL;
2273 goto out;
2274 }
2275
2276 if (!port1) {
2277 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2278 file, linenum, args[0], args[1], args[2]);
2279 err_code |= ERR_ALERT | ERR_FATAL;
2280 goto out;
2281 }
2282
2283 newmailer->addr = *sk;
2284 newmailer->proto = proto;
2285 newmailer->xprt = &raw_sock;
2286 newmailer->sock_init_arg = NULL;
2287 } /* neither "mailer" nor "mailers" */
2288 else if (*args[0] != 0) {
2289 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2290 err_code |= ERR_ALERT | ERR_FATAL;
2291 goto out;
2292 }
2293
2294out:
2295 free(errmsg);
2296 return err_code;
2297}
2298
Simon Horman9dc49962015-01-30 11:22:59 +09002299static void free_email_alert(struct proxy *p)
2300{
2301 free(p->email_alert.mailers.name);
2302 p->email_alert.mailers.name = NULL;
2303 free(p->email_alert.from);
2304 p->email_alert.from = NULL;
2305 free(p->email_alert.to);
2306 p->email_alert.to = NULL;
2307 free(p->email_alert.myhostname);
2308 p->email_alert.myhostname = NULL;
2309}
2310
Willy Tarreau3842f002009-06-14 11:39:52 +02002311int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002312{
2313 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002314 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002315 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002316 int rc;
2317 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002318 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002319 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002320 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002321 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002322 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002323
Willy Tarreau977b8e42006-12-29 14:19:17 +01002324 if (!strcmp(args[0], "listen"))
2325 rc = PR_CAP_LISTEN;
2326 else if (!strcmp(args[0], "frontend"))
2327 rc = PR_CAP_FE | PR_CAP_RS;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02002328 else if (!strcmp(args[0], "backend"))
Willy Tarreau977b8e42006-12-29 14:19:17 +01002329 rc = PR_CAP_BE | PR_CAP_RS;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002330 else
2331 rc = PR_CAP_NONE;
2332
2333 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002334 if (!*args[1]) {
2335 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
2336 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
2337 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002338 err_code |= ERR_ALERT | ERR_ABORT;
2339 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002340 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002341
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002342 err = invalid_char(args[1]);
2343 if (err) {
2344 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2345 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002346 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002347 }
2348
Willy Tarreau8f50b682015-05-26 11:45:02 +02002349 curproxy = (rc & PR_CAP_FE) ? proxy_fe_by_name(args[1]) : proxy_be_by_name(args[1]);
2350 if (curproxy) {
2351 Alert("Parsing [%s:%d]: %s '%s' has the same name as %s '%s' declared at %s:%d.\n",
2352 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2353 curproxy->id, curproxy->conf.file, curproxy->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002354 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002355 }
2356
Willy Tarreaubaaee002006-06-26 02:48:02 +02002357 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
2358 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002359 err_code |= ERR_ALERT | ERR_ABORT;
2360 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002361 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002362
Willy Tarreau97cb7802010-01-03 20:23:58 +01002363 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002364 curproxy->next = proxy;
2365 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002366 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2367 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002368 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002369 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002370 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002371 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002372
William Lallemand6e62fb62015-04-28 16:55:23 +02002373 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2374 if (curproxy->cap & PR_CAP_FE)
2375 Alert("parsing [%s:%d] : please use the 'bind' keyword for listening addresses.\n", file, linenum);
2376 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002377 }
2378
2379 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002380 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002381 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002382
Willy Tarreaubaaee002006-06-26 02:48:02 +02002383 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002384 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002385 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002386 curproxy->no_options = defproxy.no_options;
2387 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002388 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002389 curproxy->except_net = defproxy.except_net;
2390 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002391 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002392 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002393
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002394 if (defproxy.fwdfor_hdr_len) {
2395 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2396 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2397 }
2398
Willy Tarreaub86db342009-11-30 11:50:16 +01002399 if (defproxy.orgto_hdr_len) {
2400 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2401 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2402 }
2403
Mark Lamourinec2247f02012-01-04 13:02:01 -05002404 if (defproxy.server_id_hdr_len) {
2405 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2406 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2407 }
2408
Willy Tarreau977b8e42006-12-29 14:19:17 +01002409 if (curproxy->cap & PR_CAP_FE) {
2410 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002411 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002412 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002413
2414 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002415 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2416 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002417
2418 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2419 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002420
Willy Tarreau977b8e42006-12-29 14:19:17 +01002421 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002422 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002423 curproxy->fullconn = defproxy.fullconn;
2424 curproxy->conn_retries = defproxy.conn_retries;
Joseph Lynch726ab712015-05-11 23:25:34 -07002425 curproxy->redispatch_after = defproxy.redispatch_after;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002426 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002427
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002428 if (defproxy.check_req) {
2429 curproxy->check_req = calloc(1, defproxy.check_len);
2430 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2431 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002432 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002433
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002434 if (defproxy.expect_str) {
2435 curproxy->expect_str = strdup(defproxy.expect_str);
2436 if (defproxy.expect_regex) {
2437 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002438 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2439 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002440 }
2441 }
2442
Willy Tarreau67402132012-05-31 20:40:20 +02002443 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002444 if (defproxy.cookie_name)
2445 curproxy->cookie_name = strdup(defproxy.cookie_name);
2446 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002447 if (defproxy.cookie_domain)
2448 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002449
Willy Tarreau31936852010-10-06 16:59:56 +02002450 if (defproxy.cookie_maxidle)
2451 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2452
2453 if (defproxy.cookie_maxlife)
2454 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2455
Emeric Brun647caf12009-06-30 17:57:00 +02002456 if (defproxy.rdp_cookie_name)
2457 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2458 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2459
Willy Tarreau01732802007-11-01 22:48:15 +01002460 if (defproxy.url_param_name)
2461 curproxy->url_param_name = strdup(defproxy.url_param_name);
2462 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002463
Benoitaffb4812009-03-25 13:02:10 +01002464 if (defproxy.hh_name)
2465 curproxy->hh_name = strdup(defproxy.hh_name);
2466 curproxy->hh_len = defproxy.hh_len;
2467 curproxy->hh_match_domain = defproxy.hh_match_domain;
2468
Willy Tarreauef9a3602012-12-08 22:29:20 +01002469 if (defproxy.conn_src.iface_name)
2470 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2471 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002472 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02002473#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002474 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002475#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01002476 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002477
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002478 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002479 if (defproxy.capture_name)
2480 curproxy->capture_name = strdup(defproxy.capture_name);
2481 curproxy->capture_namelen = defproxy.capture_namelen;
2482 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002483 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002484
Willy Tarreau977b8e42006-12-29 14:19:17 +01002485 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002486 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002487 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002488 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002489 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002490 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002491 curproxy->mon_net = defproxy.mon_net;
2492 curproxy->mon_mask = defproxy.mon_mask;
2493 if (defproxy.monitor_uri)
2494 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2495 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002496 if (defproxy.defbe.name)
2497 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002498
2499 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002500 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2501 if (curproxy->conf.logformat_string &&
2502 curproxy->conf.logformat_string != default_http_log_format &&
2503 curproxy->conf.logformat_string != default_tcp_log_format &&
2504 curproxy->conf.logformat_string != clf_http_log_format)
2505 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2506
2507 if (defproxy.conf.lfs_file) {
2508 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2509 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2510 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002511 }
2512
2513 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002514 curproxy->timeout.connect = defproxy.timeout.connect;
2515 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002516 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002517 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002518 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002519 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002520 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002521 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002522 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002523 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002524 }
2525
Willy Tarreaubaaee002006-06-26 02:48:02 +02002526 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002527 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002528
2529 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002530 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002531 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002532 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002533 LIST_INIT(&node->list);
2534 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2535 }
2536
Willy Tarreau62a61232013-04-12 18:13:46 +02002537 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2538 if (curproxy->conf.uniqueid_format_string)
2539 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2540
Willy Tarreau094af4e2015-01-07 15:03:42 +01002541 if (defproxy.log_tag)
2542 curproxy->log_tag = strdup(defproxy.log_tag);
2543
Willy Tarreau62a61232013-04-12 18:13:46 +02002544 if (defproxy.conf.uif_file) {
2545 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2546 curproxy->conf.uif_line = defproxy.conf.uif_line;
2547 }
William Lallemanda73203e2012-03-12 12:48:57 +01002548
2549 /* copy default header unique id */
2550 if (defproxy.header_unique_id)
2551 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2552
William Lallemand82fe75c2012-10-23 10:25:10 +02002553 /* default compression options */
2554 if (defproxy.comp != NULL) {
2555 curproxy->comp = calloc(1, sizeof(struct comp));
2556 curproxy->comp->algos = defproxy.comp->algos;
2557 curproxy->comp->types = defproxy.comp->types;
2558 }
2559
Willy Tarreaubaaee002006-06-26 02:48:02 +02002560 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002561 curproxy->conf.used_listener_id = EB_ROOT;
2562 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002563
Simon Horman98637e52014-06-20 12:30:16 +09002564 if (defproxy.check_path)
2565 curproxy->check_path = strdup(defproxy.check_path);
2566 if (defproxy.check_command)
2567 curproxy->check_command = strdup(defproxy.check_command);
2568
Simon Horman9dc49962015-01-30 11:22:59 +09002569 if (defproxy.email_alert.mailers.name)
2570 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2571 if (defproxy.email_alert.from)
2572 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2573 if (defproxy.email_alert.to)
2574 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2575 if (defproxy.email_alert.myhostname)
2576 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09002577 curproxy->email_alert.level = defproxy.email_alert.level;
Simon Horman9dc49962015-01-30 11:22:59 +09002578
Willy Tarreau93893792009-07-23 13:19:11 +02002579 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002580 }
2581 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2582 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002583 /* FIXME-20070101: we should do this too at the end of the
2584 * config parsing to free all default values.
2585 */
William Lallemand6e62fb62015-04-28 16:55:23 +02002586 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2587 err_code |= ERR_ABORT;
2588 goto out;
2589 }
2590
Willy Tarreaua534fea2008-08-03 12:19:50 +02002591 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002592 free(defproxy.check_command);
2593 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002594 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002595 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002596 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002597 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002598 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002599 free(defproxy.capture_name);
2600 free(defproxy.monitor_uri);
2601 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002602 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002603 free(defproxy.fwdfor_hdr_name);
2604 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002605 free(defproxy.orgto_hdr_name);
2606 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002607 free(defproxy.server_id_hdr_name);
2608 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002609 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002610 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002611 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002612 free(defproxy.expect_regex);
2613 defproxy.expect_regex = NULL;
2614 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002615
Willy Tarreau62a61232013-04-12 18:13:46 +02002616 if (defproxy.conf.logformat_string != default_http_log_format &&
2617 defproxy.conf.logformat_string != default_tcp_log_format &&
2618 defproxy.conf.logformat_string != clf_http_log_format)
2619 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002620
Willy Tarreau62a61232013-04-12 18:13:46 +02002621 free(defproxy.conf.uniqueid_format_string);
2622 free(defproxy.conf.lfs_file);
2623 free(defproxy.conf.uif_file);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002624 free(defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09002625 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02002626
Willy Tarreaua534fea2008-08-03 12:19:50 +02002627 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002628 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002629
Willy Tarreaubaaee002006-06-26 02:48:02 +02002630 /* we cannot free uri_auth because it might already be used */
2631 init_default_instance();
2632 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002633 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2634 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002635 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002636 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002637 }
2638 else if (curproxy == NULL) {
2639 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002640 err_code |= ERR_ALERT | ERR_FATAL;
2641 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002642 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002643
2644 /* update the current file and line being parsed */
2645 curproxy->conf.args.file = curproxy->conf.file;
2646 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002647
2648 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002649 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2650 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2651 if (err_code & ERR_FATAL)
2652 goto out;
2653 }
2654 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002655 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002656 int cur_arg;
2657
Willy Tarreaubaaee002006-06-26 02:48:02 +02002658 if (curproxy == &defproxy) {
2659 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002660 err_code |= ERR_ALERT | ERR_FATAL;
2661 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002662 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002663 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002664 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002665
Willy Tarreau24709282013-03-10 21:32:12 +01002666 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002667 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002668 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002669 err_code |= ERR_ALERT | ERR_FATAL;
2670 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002671 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002672
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002673 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002674
2675 /* use default settings for unix sockets */
2676 bind_conf->ux.uid = global.unix_bind.ux.uid;
2677 bind_conf->ux.gid = global.unix_bind.ux.gid;
2678 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002679
2680 /* NOTE: the following line might create several listeners if there
2681 * are comma-separated IPs or port ranges. So all further processing
2682 * will have to be applied to all listeners created after last_listen.
2683 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002684 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2685 if (errmsg && *errmsg) {
2686 indent_msg(&errmsg, 2);
2687 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002688 }
2689 else
2690 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2691 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002692 err_code |= ERR_ALERT | ERR_FATAL;
2693 goto out;
2694 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002695
Willy Tarreau4348fad2012-09-20 16:48:07 +02002696 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2697 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002698 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002699 }
2700
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002701 cur_arg = 2;
2702 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002703 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002704 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002705 char *err;
2706
Willy Tarreau26982662012-09-12 23:17:10 +02002707 kw = bind_find_kw(args[cur_arg]);
2708 if (kw) {
2709 char *err = NULL;
2710 int code;
2711
2712 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002713 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2714 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002715 cur_arg += 1 + kw->skip ;
2716 err_code |= ERR_ALERT | ERR_FATAL;
2717 goto out;
2718 }
2719
Willy Tarreau4348fad2012-09-20 16:48:07 +02002720 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002721 err_code |= code;
2722
2723 if (code) {
2724 if (err && *err) {
2725 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002726 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002727 }
2728 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002729 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2730 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002731 if (code & ERR_FATAL) {
2732 free(err);
2733 cur_arg += 1 + kw->skip;
2734 goto out;
2735 }
2736 }
2737 free(err);
2738 cur_arg += 1 + kw->skip;
2739 continue;
2740 }
2741
Willy Tarreau8638f482012-09-18 18:01:17 +02002742 err = NULL;
2743 if (!bind_dumped) {
2744 bind_dump_kws(&err);
2745 indent_msg(&err, 4);
2746 bind_dumped = 1;
2747 }
2748
2749 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2750 file, linenum, args[0], args[1], args[cur_arg],
2751 err ? " Registered keywords :" : "", err ? err : "");
2752 free(err);
2753
Willy Tarreau93893792009-07-23 13:19:11 +02002754 err_code |= ERR_ALERT | ERR_FATAL;
2755 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002756 }
Willy Tarreau93893792009-07-23 13:19:11 +02002757 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002758 }
2759 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002760 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002761 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2762 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002763 err_code |= ERR_ALERT | ERR_FATAL;
2764 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002765 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002766 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002767 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002768
Willy Tarreaubaaee002006-06-26 02:48:02 +02002769 /* flush useless bits */
2770 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002771 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002772 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002773 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002774 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002775 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002776
William Lallemanddf1425a2015-04-28 20:17:49 +02002777 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2778 goto out;
2779
Willy Tarreau1c47f852006-07-09 08:22:27 +02002780 if (!*args[1]) {
2781 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2782 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002783 err_code |= ERR_ALERT | ERR_FATAL;
2784 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002785 }
2786
Willy Tarreaua534fea2008-08-03 12:19:50 +02002787 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002788 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002789 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002790 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002791 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2792
Willy Tarreau93893792009-07-23 13:19:11 +02002793 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002794 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002795 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
William Lallemanddf1425a2015-04-28 20:17:49 +02002796 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2797 goto out;
2798
Willy Tarreaubaaee002006-06-26 02:48:02 +02002799 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2800 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2801 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2802 else {
2803 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002804 err_code |= ERR_ALERT | ERR_FATAL;
2805 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002806 }
2807 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002808 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002809 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002810
2811 if (curproxy == &defproxy) {
2812 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2813 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002814 err_code |= ERR_ALERT | ERR_FATAL;
2815 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002816 }
2817
William Lallemanddf1425a2015-04-28 20:17:49 +02002818 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2819 goto out;
2820
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002821 if (!*args[1]) {
2822 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2823 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002824 err_code |= ERR_ALERT | ERR_FATAL;
2825 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002826 }
2827
2828 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002829 curproxy->conf.id.key = curproxy->uuid;
Willy Tarreau0d1fdf72015-05-27 16:44:02 +02002830 curproxy->options |= PR_O_FORCED_ID;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002831
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002832 if (curproxy->uuid <= 0) {
2833 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002834 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002835 err_code |= ERR_ALERT | ERR_FATAL;
2836 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002837 }
2838
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002839 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2840 if (node) {
2841 struct proxy *target = container_of(node, struct proxy, conf.id);
2842 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2843 file, linenum, proxy_type_str(curproxy), curproxy->id,
2844 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2845 err_code |= ERR_ALERT | ERR_FATAL;
2846 goto out;
2847 }
2848 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002849 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002850 else if (!strcmp(args[0], "description")) {
2851 int i, len=0;
2852 char *d;
2853
Cyril Bonté99ed3272010-01-24 23:29:44 +01002854 if (curproxy == &defproxy) {
2855 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2856 file, linenum, args[0]);
2857 err_code |= ERR_ALERT | ERR_FATAL;
2858 goto out;
2859 }
2860
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002861 if (!*args[1]) {
2862 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2863 file, linenum, args[0]);
2864 return -1;
2865 }
2866
Willy Tarreau348acfe2014-04-14 15:00:39 +02002867 for (i = 1; *args[i]; i++)
2868 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002869
2870 d = (char *)calloc(1, len);
2871 curproxy->desc = d;
2872
Willy Tarreau348acfe2014-04-14 15:00:39 +02002873 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
2874 for (i = 2; *args[i]; i++)
2875 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002876
2877 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002878 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
William Lallemanddf1425a2015-04-28 20:17:49 +02002879 if (alertif_too_many_args(0, file, linenum, args, &err_code))
2880 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002881 curproxy->state = PR_STSTOPPED;
2882 }
2883 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
William Lallemanddf1425a2015-04-28 20:17:49 +02002884 if (alertif_too_many_args(0, file, linenum, args, &err_code))
2885 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002886 curproxy->state = PR_STNEW;
2887 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002888 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2889 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002890 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002891
2892 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002893 unsigned int low, high;
2894
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002895 if (strcmp(args[cur_arg], "all") == 0) {
2896 set = 0;
2897 break;
2898 }
2899 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002900 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002901 }
2902 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002903 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002904 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002905 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002906 char *dash = strchr(args[cur_arg], '-');
2907
2908 low = high = str2uic(args[cur_arg]);
2909 if (dash)
2910 high = str2uic(dash + 1);
2911
2912 if (high < low) {
2913 unsigned int swap = low;
2914 low = high;
2915 high = swap;
2916 }
2917
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002918 if (low < 1 || high > LONGBITS) {
2919 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
2920 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02002921 err_code |= ERR_ALERT | ERR_FATAL;
2922 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002923 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002924 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002925 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002926 }
2927 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002928 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
2929 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002930 err_code |= ERR_ALERT | ERR_FATAL;
2931 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002932 }
2933 cur_arg++;
2934 }
2935 curproxy->bind_proc = set;
2936 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002937 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002938 if (curproxy == &defproxy) {
2939 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002940 err_code |= ERR_ALERT | ERR_FATAL;
2941 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002942 }
2943
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002944 err = invalid_char(args[1]);
2945 if (err) {
2946 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2947 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002948 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002949 }
2950
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01002951 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002952 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2953 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002954 err_code |= ERR_ALERT | ERR_FATAL;
2955 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002956 }
2957 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002958 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2959 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002960
Willy Tarreau977b8e42006-12-29 14:19:17 +01002961 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002962 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002963
Willy Tarreaubaaee002006-06-26 02:48:02 +02002964 if (*(args[1]) == 0) {
2965 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2966 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002967 err_code |= ERR_ALERT | ERR_FATAL;
2968 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002969 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002970
Willy Tarreau67402132012-05-31 20:40:20 +02002971 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002972 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002973 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002974 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002975 curproxy->cookie_name = strdup(args[1]);
2976 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002977
Willy Tarreaubaaee002006-06-26 02:48:02 +02002978 cur_arg = 2;
2979 while (*(args[cur_arg])) {
2980 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002981 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002982 }
2983 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002984 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002985 }
2986 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002987 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002988 }
2989 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002990 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002991 }
2992 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002993 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002994 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002995 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002996 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002997 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002998 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002999 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003000 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02003001 else if (!strcmp(args[cur_arg], "httponly")) {
3002 curproxy->ck_opts |= PR_CK_HTTPONLY;
3003 }
3004 else if (!strcmp(args[cur_arg], "secure")) {
3005 curproxy->ck_opts |= PR_CK_SECURE;
3006 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003007 else if (!strcmp(args[cur_arg], "domain")) {
3008 if (!*args[cur_arg + 1]) {
3009 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
3010 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003011 err_code |= ERR_ALERT | ERR_FATAL;
3012 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003013 }
3014
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003015 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003016 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003017 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
3018 " dots nor does not start with a dot."
3019 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003020 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003021 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003022 }
3023
3024 err = invalid_domainchar(args[cur_arg + 1]);
3025 if (err) {
3026 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
3027 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003028 err_code |= ERR_ALERT | ERR_FATAL;
3029 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003030 }
3031
Willy Tarreau68a897b2009-12-03 23:28:34 +01003032 if (!curproxy->cookie_domain) {
3033 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
3034 } else {
3035 /* one domain was already specified, add another one by
3036 * building the string which will be returned along with
3037 * the cookie.
3038 */
3039 char *new_ptr;
3040 int new_len = strlen(curproxy->cookie_domain) +
3041 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
3042 new_ptr = malloc(new_len);
3043 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
3044 free(curproxy->cookie_domain);
3045 curproxy->cookie_domain = new_ptr;
3046 }
Willy Tarreau31936852010-10-06 16:59:56 +02003047 cur_arg++;
3048 }
3049 else if (!strcmp(args[cur_arg], "maxidle")) {
3050 unsigned int maxidle;
3051 const char *res;
3052
3053 if (!*args[cur_arg + 1]) {
3054 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
3055 file, linenum, args[cur_arg]);
3056 err_code |= ERR_ALERT | ERR_FATAL;
3057 goto out;
3058 }
3059
3060 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
3061 if (res) {
3062 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3063 file, linenum, *res, args[cur_arg]);
3064 err_code |= ERR_ALERT | ERR_FATAL;
3065 goto out;
3066 }
3067 curproxy->cookie_maxidle = maxidle;
3068 cur_arg++;
3069 }
3070 else if (!strcmp(args[cur_arg], "maxlife")) {
3071 unsigned int maxlife;
3072 const char *res;
3073
3074 if (!*args[cur_arg + 1]) {
3075 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
3076 file, linenum, args[cur_arg]);
3077 err_code |= ERR_ALERT | ERR_FATAL;
3078 goto out;
3079 }
3080
3081 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
3082 if (res) {
3083 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3084 file, linenum, *res, args[cur_arg]);
3085 err_code |= ERR_ALERT | ERR_FATAL;
3086 goto out;
3087 }
3088 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003089 cur_arg++;
3090 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003091 else {
Willy Tarreau31936852010-10-06 16:59:56 +02003092 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 +02003093 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003094 err_code |= ERR_ALERT | ERR_FATAL;
3095 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003096 }
3097 cur_arg++;
3098 }
Willy Tarreau67402132012-05-31 20:40:20 +02003099 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003100 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
3101 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003102 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003103 }
3104
Willy Tarreau67402132012-05-31 20:40:20 +02003105 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003106 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
3107 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003108 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003109 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003110
Willy Tarreau67402132012-05-31 20:40:20 +02003111 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003112 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
3113 file, linenum);
3114 err_code |= ERR_ALERT | ERR_FATAL;
3115 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003116 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09003117 else if (!strcmp(args[0], "email-alert")) {
3118 if (*(args[1]) == 0) {
3119 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3120 file, linenum, args[0]);
3121 err_code |= ERR_ALERT | ERR_FATAL;
3122 goto out;
3123 }
3124
3125 if (!strcmp(args[1], "from")) {
3126 if (*(args[1]) == 0) {
3127 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3128 file, linenum, args[1]);
3129 err_code |= ERR_ALERT | ERR_FATAL;
3130 goto out;
3131 }
3132 free(curproxy->email_alert.from);
3133 curproxy->email_alert.from = strdup(args[2]);
3134 }
3135 else if (!strcmp(args[1], "mailers")) {
3136 if (*(args[1]) == 0) {
3137 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3138 file, linenum, args[1]);
3139 err_code |= ERR_ALERT | ERR_FATAL;
3140 goto out;
3141 }
3142 free(curproxy->email_alert.mailers.name);
3143 curproxy->email_alert.mailers.name = strdup(args[2]);
3144 }
3145 else if (!strcmp(args[1], "myhostname")) {
3146 if (*(args[1]) == 0) {
3147 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3148 file, linenum, args[1]);
3149 err_code |= ERR_ALERT | ERR_FATAL;
3150 goto out;
3151 }
3152 free(curproxy->email_alert.myhostname);
3153 curproxy->email_alert.myhostname = strdup(args[2]);
3154 }
Simon Horman64e34162015-02-06 11:11:57 +09003155 else if (!strcmp(args[1], "level")) {
3156 curproxy->email_alert.level = get_log_level(args[2]);
3157 if (curproxy->email_alert.level < 0) {
3158 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
3159 file, linenum, args[1], args[2]);
3160 err_code |= ERR_ALERT | ERR_FATAL;
3161 goto out;
3162 }
3163 }
Simon Horman9dc49962015-01-30 11:22:59 +09003164 else if (!strcmp(args[1], "to")) {
3165 if (*(args[1]) == 0) {
3166 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3167 file, linenum, args[1]);
3168 err_code |= ERR_ALERT | ERR_FATAL;
3169 goto out;
3170 }
3171 free(curproxy->email_alert.to);
3172 curproxy->email_alert.to = strdup(args[2]);
3173 }
3174 else {
3175 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
3176 file, linenum, args[1]);
3177 err_code |= ERR_ALERT | ERR_FATAL;
3178 goto out;
3179 }
Simon Horman64e34162015-02-06 11:11:57 +09003180 /* Indicate that the email_alert is at least partially configured */
3181 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09003182 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09003183 else if (!strcmp(args[0], "external-check")) {
3184 if (*(args[1]) == 0) {
3185 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3186 file, linenum, args[0]);
3187 err_code |= ERR_ALERT | ERR_FATAL;
3188 goto out;
3189 }
3190
3191 if (!strcmp(args[1], "command")) {
William Lallemanddf1425a2015-04-28 20:17:49 +02003192 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3193 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09003194 if (*(args[1]) == 0) {
3195 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3196 file, linenum, args[1]);
3197 err_code |= ERR_ALERT | ERR_FATAL;
3198 goto out;
3199 }
3200 free(curproxy->check_command);
3201 curproxy->check_command = strdup(args[2]);
3202 }
3203 else if (!strcmp(args[1], "path")) {
William Lallemanddf1425a2015-04-28 20:17:49 +02003204 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3205 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09003206 if (*(args[1]) == 0) {
3207 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3208 file, linenum, args[1]);
3209 err_code |= ERR_ALERT | ERR_FATAL;
3210 goto out;
3211 }
3212 free(curproxy->check_path);
3213 curproxy->check_path = strdup(args[2]);
3214 }
3215 else {
3216 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
3217 file, linenum, args[1]);
3218 err_code |= ERR_ALERT | ERR_FATAL;
3219 goto out;
3220 }
3221 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02003222 else if (!strcmp(args[0], "persist")) { /* persist */
3223 if (*(args[1]) == 0) {
3224 Alert("parsing [%s:%d] : missing persist method.\n",
3225 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003226 err_code |= ERR_ALERT | ERR_FATAL;
3227 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003228 }
3229
3230 if (!strncmp(args[1], "rdp-cookie", 10)) {
3231 curproxy->options2 |= PR_O2_RDPC_PRST;
3232
Emeric Brunb982a3d2010-01-04 15:45:53 +01003233 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003234 const char *beg, *end;
3235
3236 beg = args[1] + 11;
3237 end = strchr(beg, ')');
3238
William Lallemanddf1425a2015-04-28 20:17:49 +02003239 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3240 goto out;
3241
Emeric Brun647caf12009-06-30 17:57:00 +02003242 if (!end || end == beg) {
3243 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3244 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003245 err_code |= ERR_ALERT | ERR_FATAL;
3246 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003247 }
3248
3249 free(curproxy->rdp_cookie_name);
3250 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3251 curproxy->rdp_cookie_len = end-beg;
3252 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003253 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003254 free(curproxy->rdp_cookie_name);
3255 curproxy->rdp_cookie_name = strdup("msts");
3256 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3257 }
3258 else { /* syntax */
3259 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3260 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003261 err_code |= ERR_ALERT | ERR_FATAL;
3262 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003263 }
3264 }
3265 else {
3266 Alert("parsing [%s:%d] : unknown persist method.\n",
3267 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003268 err_code |= ERR_ALERT | ERR_FATAL;
3269 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003270 }
3271 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003272 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003273 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003274
Cyril Bonté3b7a3692010-01-10 17:01:47 +01003275 if (curproxy == &defproxy) {
3276 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3277 err_code |= ERR_ALERT | ERR_FATAL;
3278 goto out;
3279 }
3280
Willy Tarreau977b8e42006-12-29 14:19:17 +01003281 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003282 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003283
Willy Tarreaubaaee002006-06-26 02:48:02 +02003284 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01003285 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003286 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003287 err_code |= ERR_ALERT | ERR_FATAL;
3288 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003289 }
3290 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003291 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003292 curproxy->appsession_name = strdup(args[1]);
3293 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
3294 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003295 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
3296 if (err) {
3297 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
3298 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003299 err_code |= ERR_ALERT | ERR_FATAL;
3300 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003301 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003302 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02003303
Willy Tarreau51041c72007-09-09 21:56:53 +02003304 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
3305 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003306 err_code |= ERR_ALERT | ERR_ABORT;
3307 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003308 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003309
3310 cur_arg = 6;
3311 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01003312 curproxy->options2 &= ~PR_O2_AS_M_ANY;
3313 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003314 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01003315 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003316 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01003317 } else if (!strcmp(args[cur_arg], "prefix")) {
3318 curproxy->options2 |= PR_O2_AS_PFX;
3319 } else if (!strcmp(args[cur_arg], "mode")) {
3320 if (!*args[cur_arg + 1]) {
3321 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
3322 file, linenum, args[0], args[cur_arg]);
3323 err_code |= ERR_ALERT | ERR_FATAL;
3324 goto out;
3325 }
3326
3327 cur_arg++;
3328 if (!strcmp(args[cur_arg], "query-string")) {
3329 curproxy->options2 &= ~PR_O2_AS_M_ANY;
3330 curproxy->options2 |= PR_O2_AS_M_QS;
3331 } else if (!strcmp(args[cur_arg], "path-parameters")) {
3332 curproxy->options2 &= ~PR_O2_AS_M_ANY;
3333 curproxy->options2 |= PR_O2_AS_M_PP;
3334 } else {
3335 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
3336 err_code |= ERR_ALERT | ERR_FATAL;
3337 goto out;
3338 }
3339 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003340 cur_arg++;
3341 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003342 } /* Url App Session */
3343 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003344 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003345 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003346
Willy Tarreaubaaee002006-06-26 02:48:02 +02003347 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003348 if (curproxy == &defproxy) {
3349 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3350 err_code |= ERR_ALERT | ERR_FATAL;
3351 goto out;
3352 }
3353
William Lallemand1a748ae2015-05-19 16:37:23 +02003354 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3355 goto out;
3356
Willy Tarreaubaaee002006-06-26 02:48:02 +02003357 if (*(args[4]) == 0) {
3358 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3359 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003360 err_code |= ERR_ALERT | ERR_FATAL;
3361 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003362 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003363 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003364 curproxy->capture_name = strdup(args[2]);
3365 curproxy->capture_namelen = strlen(curproxy->capture_name);
3366 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003367 curproxy->to_log |= LW_COOKIE;
3368 }
3369 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3370 struct cap_hdr *hdr;
3371
3372 if (curproxy == &defproxy) {
3373 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 +02003374 err_code |= ERR_ALERT | ERR_FATAL;
3375 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003376 }
3377
William Lallemand1a748ae2015-05-19 16:37:23 +02003378 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3379 goto out;
3380
Willy Tarreaubaaee002006-06-26 02:48:02 +02003381 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3382 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3383 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003384 err_code |= ERR_ALERT | ERR_FATAL;
3385 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003386 }
3387
3388 hdr = calloc(sizeof(struct cap_hdr), 1);
3389 hdr->next = curproxy->req_cap;
3390 hdr->name = strdup(args[3]);
3391 hdr->namelen = strlen(args[3]);
3392 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003393 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003394 hdr->index = curproxy->nb_req_cap++;
3395 curproxy->req_cap = hdr;
3396 curproxy->to_log |= LW_REQHDR;
3397 }
3398 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3399 struct cap_hdr *hdr;
3400
3401 if (curproxy == &defproxy) {
3402 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 +02003403 err_code |= ERR_ALERT | ERR_FATAL;
3404 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003405 }
3406
William Lallemand1a748ae2015-05-19 16:37:23 +02003407 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3408 goto out;
3409
Willy Tarreaubaaee002006-06-26 02:48:02 +02003410 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3411 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3412 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003413 err_code |= ERR_ALERT | ERR_FATAL;
3414 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003415 }
3416 hdr = calloc(sizeof(struct cap_hdr), 1);
3417 hdr->next = curproxy->rsp_cap;
3418 hdr->name = strdup(args[3]);
3419 hdr->namelen = strlen(args[3]);
3420 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003421 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003422 hdr->index = curproxy->nb_rsp_cap++;
3423 curproxy->rsp_cap = hdr;
3424 curproxy->to_log |= LW_RSPHDR;
3425 }
3426 else {
3427 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3428 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003429 err_code |= ERR_ALERT | ERR_FATAL;
3430 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003431 }
3432 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003433 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003434 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003435 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003436
William Lallemanddf1425a2015-04-28 20:17:49 +02003437 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3438 goto out;
3439
Willy Tarreaubaaee002006-06-26 02:48:02 +02003440 if (*(args[1]) == 0) {
3441 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3442 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003443 err_code |= ERR_ALERT | ERR_FATAL;
3444 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003445 }
3446 curproxy->conn_retries = atol(args[1]);
3447 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003448 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003449 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003450
3451 if (curproxy == &defproxy) {
3452 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3453 err_code |= ERR_ALERT | ERR_FATAL;
3454 goto out;
3455 }
3456
Willy Tarreau20b0de52012-12-24 15:45:22 +01003457 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
3458 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
3459 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
3460 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003461 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01003462 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
3463 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 +01003464 file, linenum, args[0]);
3465 err_code |= ERR_WARN;
3466 }
3467
Willy Tarreauff011f22011-01-06 17:51:27 +01003468 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003469
Willy Tarreauff011f22011-01-06 17:51:27 +01003470 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003471 err_code |= ERR_ALERT | ERR_ABORT;
3472 goto out;
3473 }
3474
Willy Tarreau5002f572014-04-23 01:32:02 +02003475 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003476 err_code |= warnif_cond_conflicts(rule->cond,
3477 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3478 file, linenum);
3479
Willy Tarreauff011f22011-01-06 17:51:27 +01003480 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003481 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003482 else if (!strcmp(args[0], "http-response")) { /* response access control */
3483 struct http_res_rule *rule;
3484
3485 if (curproxy == &defproxy) {
3486 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3487 err_code |= ERR_ALERT | ERR_FATAL;
3488 goto out;
3489 }
3490
3491 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
3492 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
3493 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
3494 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
3495 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3496 file, linenum, args[0]);
3497 err_code |= ERR_WARN;
3498 }
3499
3500 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3501
3502 if (!rule) {
3503 err_code |= ERR_ALERT | ERR_ABORT;
3504 goto out;
3505 }
3506
3507 err_code |= warnif_cond_conflicts(rule->cond,
3508 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3509 file, linenum);
3510
3511 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3512 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003513 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3514 /* set the header name and length into the proxy structure */
3515 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3516 err_code |= ERR_WARN;
3517
3518 if (!*args[1]) {
3519 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3520 file, linenum, args[0]);
3521 err_code |= ERR_ALERT | ERR_FATAL;
3522 goto out;
3523 }
3524
3525 /* set the desired header name */
3526 free(curproxy->server_id_hdr_name);
3527 curproxy->server_id_hdr_name = strdup(args[1]);
3528 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3529 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003530 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003531 struct http_req_rule *rule;
3532
Willy Tarreaub099aca2008-10-12 17:26:37 +02003533 if (curproxy == &defproxy) {
3534 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003535 err_code |= ERR_ALERT | ERR_FATAL;
3536 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003537 }
3538
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003539 /* emulate "block" using "http-request block". Since these rules are supposed to
3540 * be processed before all http-request rules, we put them into their own list
3541 * and will insert them at the end.
3542 */
3543 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3544 if (!rule) {
3545 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003546 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003547 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003548 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3549 err_code |= warnif_cond_conflicts(rule->cond,
3550 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3551 file, linenum);
3552 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003553
3554 if (!already_warned(WARN_BLOCK_DEPRECATED))
3555 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]);
3556
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003557 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003558 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003559 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003560
Cyril Bonté99ed3272010-01-24 23:29:44 +01003561 if (curproxy == &defproxy) {
3562 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3563 err_code |= ERR_ALERT | ERR_FATAL;
3564 goto out;
3565 }
3566
Willy Tarreaube4653b2015-05-28 15:26:58 +02003567 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003568 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3569 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003570 err_code |= ERR_ALERT | ERR_FATAL;
3571 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003572 }
3573
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003574 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003575 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003576 err_code |= warnif_cond_conflicts(rule->cond,
3577 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3578 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003579 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003580 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003581 struct switching_rule *rule;
3582
Willy Tarreaub099aca2008-10-12 17:26:37 +02003583 if (curproxy == &defproxy) {
3584 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003585 err_code |= ERR_ALERT | ERR_FATAL;
3586 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003587 }
3588
Willy Tarreau55ea7572007-06-17 19:56:27 +02003589 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003590 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003591
3592 if (*(args[1]) == 0) {
3593 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003594 err_code |= ERR_ALERT | ERR_FATAL;
3595 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003596 }
3597
Willy Tarreauf51658d2014-04-23 01:21:56 +02003598 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3599 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3600 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3601 file, linenum, errmsg);
3602 err_code |= ERR_ALERT | ERR_FATAL;
3603 goto out;
3604 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003605
Willy Tarreauf51658d2014-04-23 01:21:56 +02003606 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003607 }
3608
3609 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
3610 rule->cond = cond;
3611 rule->be.name = strdup(args[1]);
3612 LIST_INIT(&rule->list);
3613 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3614 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003615 else if (strcmp(args[0], "use-server") == 0) {
3616 struct server_rule *rule;
3617
3618 if (curproxy == &defproxy) {
3619 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3620 err_code |= ERR_ALERT | ERR_FATAL;
3621 goto out;
3622 }
3623
3624 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3625 err_code |= ERR_WARN;
3626
3627 if (*(args[1]) == 0) {
3628 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3629 err_code |= ERR_ALERT | ERR_FATAL;
3630 goto out;
3631 }
3632
3633 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3634 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3635 file, linenum, args[0]);
3636 err_code |= ERR_ALERT | ERR_FATAL;
3637 goto out;
3638 }
3639
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003640 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3641 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3642 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003643 err_code |= ERR_ALERT | ERR_FATAL;
3644 goto out;
3645 }
3646
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003647 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003648
3649 rule = (struct server_rule *)calloc(1, sizeof(*rule));
3650 rule->cond = cond;
3651 rule->srv.name = strdup(args[1]);
3652 LIST_INIT(&rule->list);
3653 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3654 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3655 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003656 else if ((!strcmp(args[0], "force-persist")) ||
3657 (!strcmp(args[0], "ignore-persist"))) {
3658 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003659
3660 if (curproxy == &defproxy) {
3661 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3662 err_code |= ERR_ALERT | ERR_FATAL;
3663 goto out;
3664 }
3665
3666 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3667 err_code |= ERR_WARN;
3668
Willy Tarreauef6494c2010-01-28 17:12:36 +01003669 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003670 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3671 file, linenum, args[0]);
3672 err_code |= ERR_ALERT | ERR_FATAL;
3673 goto out;
3674 }
3675
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003676 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3677 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3678 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003679 err_code |= ERR_ALERT | ERR_FATAL;
3680 goto out;
3681 }
3682
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003683 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3684 * where force-persist is applied.
3685 */
3686 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003687
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003688 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003689 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003690 if (!strcmp(args[0], "force-persist")) {
3691 rule->type = PERSIST_TYPE_FORCE;
3692 } else {
3693 rule->type = PERSIST_TYPE_IGNORE;
3694 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003695 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003696 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003697 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003698 else if (!strcmp(args[0], "stick-table")) {
3699 int myidx = 1;
Willy Tarreaue45288c2015-05-26 10:49:46 +02003700 struct proxy *other;
3701
Willy Tarreaue2dc1fa2015-05-26 12:08:07 +02003702 other = proxy_tbl_by_name(curproxy->id);
Willy Tarreaue45288c2015-05-26 10:49:46 +02003703 if (other) {
3704 Alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
3705 file, linenum, curproxy->id, proxy_type_str(other), other->id, other->conf.file, other->conf.line);
3706 err_code |= ERR_ALERT | ERR_FATAL;
3707 goto out;
3708 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003709
Emeric Brun32da3c42010-09-23 18:39:19 +02003710 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003711 curproxy->table.type = (unsigned int)-1;
3712 while (*args[myidx]) {
3713 const char *err;
3714
3715 if (strcmp(args[myidx], "size") == 0) {
3716 myidx++;
3717 if (!*(args[myidx])) {
3718 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3719 file, linenum, args[myidx-1]);
3720 err_code |= ERR_ALERT | ERR_FATAL;
3721 goto out;
3722 }
3723 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3724 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3725 file, linenum, *err, args[myidx-1]);
3726 err_code |= ERR_ALERT | ERR_FATAL;
3727 goto out;
3728 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003729 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003730 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003731 else if (strcmp(args[myidx], "peers") == 0) {
3732 myidx++;
Godbach50523162013-12-11 19:48:57 +08003733 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003734 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3735 file, linenum, args[myidx-1]);
3736 err_code |= ERR_ALERT | ERR_FATAL;
3737 goto out;
Godbach50523162013-12-11 19:48:57 +08003738 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003739 curproxy->table.peers.name = strdup(args[myidx++]);
3740 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003741 else if (strcmp(args[myidx], "expire") == 0) {
3742 myidx++;
3743 if (!*(args[myidx])) {
3744 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3745 file, linenum, args[myidx-1]);
3746 err_code |= ERR_ALERT | ERR_FATAL;
3747 goto out;
3748 }
3749 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3750 if (err) {
3751 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3752 file, linenum, *err, args[myidx-1]);
3753 err_code |= ERR_ALERT | ERR_FATAL;
3754 goto out;
3755 }
3756 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003757 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003758 }
3759 else if (strcmp(args[myidx], "nopurge") == 0) {
3760 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003761 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003762 }
3763 else if (strcmp(args[myidx], "type") == 0) {
3764 myidx++;
3765 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3766 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3767 file, linenum, args[myidx]);
3768 err_code |= ERR_ALERT | ERR_FATAL;
3769 goto out;
3770 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003771 /* myidx already points to next arg */
3772 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003773 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003774 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003775 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003776
3777 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003778 nw = args[myidx];
3779 while (*nw) {
3780 /* the "store" keyword supports a comma-separated list */
3781 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003782 sa = NULL; /* store arg */
3783 while (*nw && *nw != ',') {
3784 if (*nw == '(') {
3785 *nw = 0;
3786 sa = ++nw;
3787 while (*nw != ')') {
3788 if (!*nw) {
3789 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3790 file, linenum, args[0], cw);
3791 err_code |= ERR_ALERT | ERR_FATAL;
3792 goto out;
3793 }
3794 nw++;
3795 }
3796 *nw = '\0';
3797 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003798 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003799 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003800 if (*nw)
3801 *nw++ = '\0';
3802 type = stktable_get_data_type(cw);
3803 if (type < 0) {
3804 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3805 file, linenum, args[0], cw);
3806 err_code |= ERR_ALERT | ERR_FATAL;
3807 goto out;
3808 }
Willy Tarreauac782882010-06-20 10:41:54 +02003809
3810 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3811 switch (err) {
3812 case PE_NONE: break;
3813 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003814 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3815 file, linenum, args[0], cw);
3816 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003817 break;
3818
3819 case PE_ARG_MISSING:
3820 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3821 file, linenum, args[0], cw);
3822 err_code |= ERR_ALERT | ERR_FATAL;
3823 goto out;
3824
3825 case PE_ARG_NOT_USED:
3826 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3827 file, linenum, args[0], cw);
3828 err_code |= ERR_ALERT | ERR_FATAL;
3829 goto out;
3830
3831 default:
3832 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3833 file, linenum, args[0], cw);
3834 err_code |= ERR_ALERT | ERR_FATAL;
3835 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003836 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003837 }
3838 myidx++;
3839 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003840 else {
3841 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3842 file, linenum, args[myidx]);
3843 err_code |= ERR_ALERT | ERR_FATAL;
3844 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003845 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003846 }
3847
3848 if (!curproxy->table.size) {
3849 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3850 file, linenum);
3851 err_code |= ERR_ALERT | ERR_FATAL;
3852 goto out;
3853 }
3854
3855 if (curproxy->table.type == (unsigned int)-1) {
3856 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3857 file, linenum);
3858 err_code |= ERR_ALERT | ERR_FATAL;
3859 goto out;
3860 }
3861 }
3862 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003863 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003864 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003865 int myidx = 0;
3866 const char *name = NULL;
3867 int flags;
3868
3869 if (curproxy == &defproxy) {
3870 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3871 err_code |= ERR_ALERT | ERR_FATAL;
3872 goto out;
3873 }
3874
3875 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3876 err_code |= ERR_WARN;
3877 goto out;
3878 }
3879
3880 myidx++;
3881 if ((strcmp(args[myidx], "store") == 0) ||
3882 (strcmp(args[myidx], "store-request") == 0)) {
3883 myidx++;
3884 flags = STK_IS_STORE;
3885 }
3886 else if (strcmp(args[myidx], "store-response") == 0) {
3887 myidx++;
3888 flags = STK_IS_STORE | STK_ON_RSP;
3889 }
3890 else if (strcmp(args[myidx], "match") == 0) {
3891 myidx++;
3892 flags = STK_IS_MATCH;
3893 }
3894 else if (strcmp(args[myidx], "on") == 0) {
3895 myidx++;
3896 flags = STK_IS_MATCH | STK_IS_STORE;
3897 }
3898 else {
3899 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3900 err_code |= ERR_ALERT | ERR_FATAL;
3901 goto out;
3902 }
3903
3904 if (*(args[myidx]) == 0) {
3905 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3906 err_code |= ERR_ALERT | ERR_FATAL;
3907 goto out;
3908 }
3909
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003910 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01003911 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003912 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01003913 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003914 err_code |= ERR_ALERT | ERR_FATAL;
3915 goto out;
3916 }
3917
3918 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003919 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3920 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3921 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003922 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003923 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003924 goto out;
3925 }
3926 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003927 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3928 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3929 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003930 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003931 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003932 goto out;
3933 }
3934 }
3935
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003936 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003937 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003938
Emeric Brunb982a3d2010-01-04 15:45:53 +01003939 if (strcmp(args[myidx], "table") == 0) {
3940 myidx++;
3941 name = args[myidx++];
3942 }
3943
Willy Tarreauef6494c2010-01-28 17:12:36 +01003944 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003945 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3946 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3947 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003948 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003949 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003950 goto out;
3951 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003952 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003953 else if (*(args[myidx])) {
3954 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3955 file, linenum, args[0], args[myidx]);
3956 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003957 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003958 goto out;
3959 }
Emeric Brun97679e72010-09-23 17:56:44 +02003960 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003961 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003962 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003963 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003964
Emeric Brunb982a3d2010-01-04 15:45:53 +01003965 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3966 rule->cond = cond;
3967 rule->expr = expr;
3968 rule->flags = flags;
3969 rule->table.name = name ? strdup(name) : NULL;
3970 LIST_INIT(&rule->list);
3971 if (flags & STK_ON_RSP)
3972 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3973 else
3974 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3975 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003976 else if (!strcmp(args[0], "stats")) {
3977 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3978 curproxy->uri_auth = NULL; /* we must detach from the default config */
3979
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003980 if (!*args[1]) {
3981 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003982 } else if (!strcmp(args[1], "admin")) {
3983 struct stats_admin_rule *rule;
3984
3985 if (curproxy == &defproxy) {
3986 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3987 err_code |= ERR_ALERT | ERR_FATAL;
3988 goto out;
3989 }
3990
3991 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3992 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3993 err_code |= ERR_ALERT | ERR_ABORT;
3994 goto out;
3995 }
3996
3997 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3998 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3999 file, linenum, args[0], args[1]);
4000 err_code |= ERR_ALERT | ERR_FATAL;
4001 goto out;
4002 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004003 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4004 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
4005 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02004006 err_code |= ERR_ALERT | ERR_FATAL;
4007 goto out;
4008 }
4009
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004010 err_code |= warnif_cond_conflicts(cond,
4011 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4012 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02004013
4014 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
4015 rule->cond = cond;
4016 LIST_INIT(&rule->list);
4017 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004018 } else if (!strcmp(args[1], "uri")) {
4019 if (*(args[2]) == 0) {
4020 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004021 err_code |= ERR_ALERT | ERR_FATAL;
4022 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004023 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
4024 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004025 err_code |= ERR_ALERT | ERR_ABORT;
4026 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004027 }
4028 } else if (!strcmp(args[1], "realm")) {
4029 if (*(args[2]) == 0) {
4030 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004031 err_code |= ERR_ALERT | ERR_FATAL;
4032 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004033 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
4034 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004035 err_code |= ERR_ALERT | ERR_ABORT;
4036 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004037 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02004038 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004039 unsigned interval;
4040
4041 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
4042 if (err) {
4043 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
4044 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004045 err_code |= ERR_ALERT | ERR_FATAL;
4046 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004047 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
4048 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004049 err_code |= ERR_ALERT | ERR_ABORT;
4050 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004051 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004052 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01004053 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004054
4055 if (curproxy == &defproxy) {
4056 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4057 err_code |= ERR_ALERT | ERR_FATAL;
4058 goto out;
4059 }
4060
4061 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4062 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4063 err_code |= ERR_ALERT | ERR_ABORT;
4064 goto out;
4065 }
4066
Willy Tarreauff011f22011-01-06 17:51:27 +01004067 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
4068 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004069 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
4070 file, linenum, args[0]);
4071 err_code |= ERR_WARN;
4072 }
4073
Willy Tarreauff011f22011-01-06 17:51:27 +01004074 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004075
Willy Tarreauff011f22011-01-06 17:51:27 +01004076 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004077 err_code |= ERR_ALERT | ERR_ABORT;
4078 goto out;
4079 }
4080
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004081 err_code |= warnif_cond_conflicts(rule->cond,
4082 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4083 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01004084 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004085
Willy Tarreaubaaee002006-06-26 02:48:02 +02004086 } else if (!strcmp(args[1], "auth")) {
4087 if (*(args[2]) == 0) {
4088 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004089 err_code |= ERR_ALERT | ERR_FATAL;
4090 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004091 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
4092 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004093 err_code |= ERR_ALERT | ERR_ABORT;
4094 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004095 }
4096 } else if (!strcmp(args[1], "scope")) {
4097 if (*(args[2]) == 0) {
4098 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004099 err_code |= ERR_ALERT | ERR_FATAL;
4100 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004101 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
4102 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004103 err_code |= ERR_ALERT | ERR_ABORT;
4104 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004105 }
4106 } else if (!strcmp(args[1], "enable")) {
4107 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4108 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004109 err_code |= ERR_ALERT | ERR_ABORT;
4110 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004111 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004112 } else if (!strcmp(args[1], "hide-version")) {
4113 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
4114 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004115 err_code |= ERR_ALERT | ERR_ABORT;
4116 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004117 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01004118 } else if (!strcmp(args[1], "show-legends")) {
4119 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
4120 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4121 err_code |= ERR_ALERT | ERR_ABORT;
4122 goto out;
4123 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004124 } else if (!strcmp(args[1], "show-node")) {
4125
4126 if (*args[2]) {
4127 int i;
4128 char c;
4129
4130 for (i=0; args[2][i]; i++) {
4131 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01004132 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
4133 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004134 break;
4135 }
4136
4137 if (!i || args[2][i]) {
4138 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
4139 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
4140 file, linenum, args[0], args[1]);
4141 err_code |= ERR_ALERT | ERR_FATAL;
4142 goto out;
4143 }
4144 }
4145
4146 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
4147 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4148 err_code |= ERR_ALERT | ERR_ABORT;
4149 goto out;
4150 }
4151 } else if (!strcmp(args[1], "show-desc")) {
4152 char *desc = NULL;
4153
4154 if (*args[2]) {
4155 int i, len=0;
4156 char *d;
4157
Willy Tarreau348acfe2014-04-14 15:00:39 +02004158 for (i = 2; *args[i]; i++)
4159 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004160
4161 desc = d = (char *)calloc(1, len);
4162
Willy Tarreau348acfe2014-04-14 15:00:39 +02004163 d += snprintf(d, desc + len - d, "%s", args[2]);
4164 for (i = 3; *args[i]; i++)
4165 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004166 }
4167
4168 if (!*args[2] && !global.desc)
4169 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
4170 file, linenum, args[1]);
4171 else {
4172 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
4173 free(desc);
4174 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4175 err_code |= ERR_ALERT | ERR_ABORT;
4176 goto out;
4177 }
4178 free(desc);
4179 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004180 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004181stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02004182 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 +01004183 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004184 err_code |= ERR_ALERT | ERR_FATAL;
4185 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004186 }
4187 }
4188 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004189 int optnum;
4190
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004191 if (*(args[1]) == '\0') {
4192 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
4193 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004194 err_code |= ERR_ALERT | ERR_FATAL;
4195 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004196 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01004197
4198 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
4199 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004200 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
4201 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4202 file, linenum, cfg_opts[optnum].name);
4203 err_code |= ERR_ALERT | ERR_FATAL;
4204 goto out;
4205 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004206 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4207 goto out;
4208
Willy Tarreau93893792009-07-23 13:19:11 +02004209 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
4210 err_code |= ERR_WARN;
4211 goto out;
4212 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004213
Willy Tarreau3842f002009-06-14 11:39:52 +02004214 curproxy->no_options &= ~cfg_opts[optnum].val;
4215 curproxy->options &= ~cfg_opts[optnum].val;
4216
4217 switch (kwm) {
4218 case KWM_STD:
4219 curproxy->options |= cfg_opts[optnum].val;
4220 break;
4221 case KWM_NO:
4222 curproxy->no_options |= cfg_opts[optnum].val;
4223 break;
4224 case KWM_DEF: /* already cleared */
4225 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004226 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004227
Willy Tarreau93893792009-07-23 13:19:11 +02004228 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004229 }
4230 }
4231
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004232 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
4233 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004234 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
4235 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4236 file, linenum, cfg_opts2[optnum].name);
4237 err_code |= ERR_ALERT | ERR_FATAL;
4238 goto out;
4239 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004240 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4241 goto out;
Willy Tarreau93893792009-07-23 13:19:11 +02004242 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4243 err_code |= ERR_WARN;
4244 goto out;
4245 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004246
Willy Tarreau3842f002009-06-14 11:39:52 +02004247 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4248 curproxy->options2 &= ~cfg_opts2[optnum].val;
4249
4250 switch (kwm) {
4251 case KWM_STD:
4252 curproxy->options2 |= cfg_opts2[optnum].val;
4253 break;
4254 case KWM_NO:
4255 curproxy->no_options2 |= cfg_opts2[optnum].val;
4256 break;
4257 case KWM_DEF: /* already cleared */
4258 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004259 }
Willy Tarreau93893792009-07-23 13:19:11 +02004260 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004261 }
4262 }
4263
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004264 /* HTTP options override each other. They can be cancelled using
4265 * "no option xxx" which only switches to default mode if the mode
4266 * was this one (useful for cancelling options set in defaults
4267 * sections).
4268 */
4269 if (strcmp(args[1], "httpclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004270 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4271 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004272 if (kwm == KWM_STD) {
4273 curproxy->options &= ~PR_O_HTTP_MODE;
4274 curproxy->options |= PR_O_HTTP_PCL;
4275 goto out;
4276 }
4277 else if (kwm == KWM_NO) {
4278 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4279 curproxy->options &= ~PR_O_HTTP_MODE;
4280 goto out;
4281 }
4282 }
4283 else if (strcmp(args[1], "forceclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004284 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4285 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004286 if (kwm == KWM_STD) {
4287 curproxy->options &= ~PR_O_HTTP_MODE;
4288 curproxy->options |= PR_O_HTTP_FCL;
4289 goto out;
4290 }
4291 else if (kwm == KWM_NO) {
4292 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4293 curproxy->options &= ~PR_O_HTTP_MODE;
4294 goto out;
4295 }
4296 }
4297 else if (strcmp(args[1], "http-server-close") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004298 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4299 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004300 if (kwm == KWM_STD) {
4301 curproxy->options &= ~PR_O_HTTP_MODE;
4302 curproxy->options |= PR_O_HTTP_SCL;
4303 goto out;
4304 }
4305 else if (kwm == KWM_NO) {
4306 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4307 curproxy->options &= ~PR_O_HTTP_MODE;
4308 goto out;
4309 }
4310 }
4311 else if (strcmp(args[1], "http-keep-alive") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004312 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4313 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004314 if (kwm == KWM_STD) {
4315 curproxy->options &= ~PR_O_HTTP_MODE;
4316 curproxy->options |= PR_O_HTTP_KAL;
4317 goto out;
4318 }
4319 else if (kwm == KWM_NO) {
4320 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4321 curproxy->options &= ~PR_O_HTTP_MODE;
4322 goto out;
4323 }
4324 }
4325 else if (strcmp(args[1], "http-tunnel") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004326 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4327 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004328 if (kwm == KWM_STD) {
4329 curproxy->options &= ~PR_O_HTTP_MODE;
4330 curproxy->options |= PR_O_HTTP_TUN;
4331 goto out;
4332 }
4333 else if (kwm == KWM_NO) {
4334 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4335 curproxy->options &= ~PR_O_HTTP_MODE;
4336 goto out;
4337 }
4338 }
4339
Joseph Lynch726ab712015-05-11 23:25:34 -07004340 /* Redispatch can take an integer argument that control when the
4341 * resispatch occurs. All values are relative to the retries option.
4342 * This can be cancelled using "no option xxx".
4343 */
4344 if (strcmp(args[1], "redispatch") == 0) {
4345 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
4346 err_code |= ERR_WARN;
4347 goto out;
4348 }
4349
4350 curproxy->no_options &= ~PR_O_REDISP;
4351 curproxy->options &= ~PR_O_REDISP;
4352
4353 switch (kwm) {
4354 case KWM_STD:
4355 curproxy->options |= PR_O_REDISP;
4356 curproxy->redispatch_after = -1;
4357 if(*args[2]) {
4358 curproxy->redispatch_after = atol(args[2]);
4359 }
4360 break;
4361 case KWM_NO:
4362 curproxy->no_options |= PR_O_REDISP;
4363 curproxy->redispatch_after = 0;
4364 break;
4365 case KWM_DEF: /* already cleared */
4366 break;
4367 }
4368 goto out;
4369 }
4370
Willy Tarreau3842f002009-06-14 11:39:52 +02004371 if (kwm != KWM_STD) {
4372 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004373 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004374 err_code |= ERR_ALERT | ERR_FATAL;
4375 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004376 }
4377
Emeric Brun3a058f32009-06-30 18:26:00 +02004378 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004379 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004380 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004381 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004382 if (*(args[2]) != '\0') {
4383 if (!strcmp(args[2], "clf")) {
4384 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004385 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004386 } else {
William Lallemand77063bc2015-05-28 18:02:48 +02004387 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004388 err_code |= ERR_ALERT | ERR_FATAL;
4389 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004390 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004391 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
4392 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004393 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004394 if (curproxy->conf.logformat_string != default_http_log_format &&
4395 curproxy->conf.logformat_string != default_tcp_log_format &&
4396 curproxy->conf.logformat_string != clf_http_log_format)
4397 free(curproxy->conf.logformat_string);
4398 curproxy->conf.logformat_string = logformat;
4399
4400 free(curproxy->conf.lfs_file);
4401 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4402 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004403 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004404 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004405 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004406 if (curproxy->conf.logformat_string != default_http_log_format &&
4407 curproxy->conf.logformat_string != default_tcp_log_format &&
4408 curproxy->conf.logformat_string != clf_http_log_format)
4409 free(curproxy->conf.logformat_string);
4410 curproxy->conf.logformat_string = default_tcp_log_format;
4411
4412 free(curproxy->conf.lfs_file);
4413 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4414 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemanddf1425a2015-04-28 20:17:49 +02004415
4416 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4417 goto out;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004418 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004419 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004420 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004421 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004422 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004423
William Lallemanddf1425a2015-04-28 20:17:49 +02004424 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4425 goto out;
4426
Willy Tarreau13943ab2006-12-31 00:24:10 +01004427 if (curproxy->cap & PR_CAP_FE)
4428 curproxy->options |= PR_O_TCP_CLI_KA;
4429 if (curproxy->cap & PR_CAP_BE)
4430 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004431 }
4432 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004433 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004434 err_code |= ERR_WARN;
4435
Willy Tarreaubaaee002006-06-26 02:48:02 +02004436 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004437 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004438 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004439 curproxy->options2 &= ~PR_O2_CHK_ANY;
4440 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004441 if (!*args[2]) { /* no argument */
4442 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4443 curproxy->check_len = strlen(DEF_CHECK_REQ);
4444 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004445 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004446 curproxy->check_req = (char *)malloc(reqlen);
4447 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004448 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004449 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004450 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004451 if (*args[4])
4452 reqlen += strlen(args[4]);
4453 else
4454 reqlen += strlen("HTTP/1.0");
4455
4456 curproxy->check_req = (char *)malloc(reqlen);
4457 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004458 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004459 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004460 if (alertif_too_many_args_idx(3, 1, file, linenum, args, &err_code))
4461 goto out;
Willy Tarreauf3c69202006-07-09 16:42:34 +02004462 }
4463 else if (!strcmp(args[1], "ssl-hello-chk")) {
4464 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004465 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004466 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004467
Willy Tarreaua534fea2008-08-03 12:19:50 +02004468 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004469 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004470 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004471 curproxy->options2 |= PR_O2_SSL3_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004472
4473 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4474 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004475 }
Willy Tarreau23677902007-05-08 23:50:35 +02004476 else if (!strcmp(args[1], "smtpchk")) {
4477 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004478 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004479 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004480 curproxy->options2 &= ~PR_O2_CHK_ANY;
4481 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004482
4483 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4484 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4485 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4486 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4487 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4488 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
4489 curproxy->check_req = (char *)malloc(reqlen);
4490 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4491 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4492 } else {
4493 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4494 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4495 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4496 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4497 }
4498 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004499 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4500 goto out;
Willy Tarreau23677902007-05-08 23:50:35 +02004501 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004502 else if (!strcmp(args[1], "pgsql-check")) {
4503 /* use PostgreSQL request to check servers' health */
4504 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4505 err_code |= ERR_WARN;
4506
4507 free(curproxy->check_req);
4508 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004509 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004510 curproxy->options2 |= PR_O2_PGSQL_CHK;
4511
4512 if (*(args[2])) {
4513 int cur_arg = 2;
4514
4515 while (*(args[cur_arg])) {
4516 if (strcmp(args[cur_arg], "user") == 0) {
4517 char * packet;
4518 uint32_t packet_len;
4519 uint32_t pv;
4520
4521 /* suboption header - needs additional argument for it */
4522 if (*(args[cur_arg+1]) == 0) {
4523 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4524 file, linenum, args[0], args[1], args[cur_arg]);
4525 err_code |= ERR_ALERT | ERR_FATAL;
4526 goto out;
4527 }
4528
4529 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4530 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4531 pv = htonl(0x30000); /* protocol version 3.0 */
4532
4533 packet = (char*) calloc(1, packet_len);
4534
4535 memcpy(packet + 4, &pv, 4);
4536
4537 /* copy "user" */
4538 memcpy(packet + 8, "user", 4);
4539
4540 /* copy username */
4541 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4542
4543 free(curproxy->check_req);
4544 curproxy->check_req = packet;
4545 curproxy->check_len = packet_len;
4546
4547 packet_len = htonl(packet_len);
4548 memcpy(packet, &packet_len, 4);
4549 cur_arg += 2;
4550 } else {
4551 /* unknown suboption - catchall */
4552 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4553 file, linenum, args[0], args[1]);
4554 err_code |= ERR_ALERT | ERR_FATAL;
4555 goto out;
4556 }
4557 } /* end while loop */
4558 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004559 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4560 goto out;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004561 }
4562
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004563 else if (!strcmp(args[1], "redis-check")) {
4564 /* use REDIS PING request to check servers' health */
4565 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4566 err_code |= ERR_WARN;
4567
4568 free(curproxy->check_req);
4569 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004570 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004571 curproxy->options2 |= PR_O2_REDIS_CHK;
4572
4573 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
4574 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4575 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004576
4577 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4578 goto out;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004579 }
4580
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004581 else if (!strcmp(args[1], "mysql-check")) {
4582 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004583 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4584 err_code |= ERR_WARN;
4585
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004586 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004587 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004588 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004589 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004590
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004591 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004592 * const char mysql40_client_auth_pkt[] = {
4593 * "\x0e\x00\x00" // packet length
4594 * "\x01" // packet number
4595 * "\x00\x00" // client capabilities
4596 * "\x00\x00\x01" // max packet
4597 * "haproxy\x00" // username (null terminated string)
4598 * "\x00" // filler (always 0x00)
4599 * "\x01\x00\x00" // packet length
4600 * "\x00" // packet number
4601 * "\x01" // COM_QUIT command
4602 * };
4603 */
4604
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004605 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4606 * const char mysql41_client_auth_pkt[] = {
4607 * "\x0e\x00\x00\" // packet length
4608 * "\x01" // packet number
4609 * "\x00\x00\x00\x00" // client capabilities
4610 * "\x00\x00\x00\x01" // max packet
4611 * "\x21" // character set (UTF-8)
4612 * char[23] // All zeroes
4613 * "haproxy\x00" // username (null terminated string)
4614 * "\x00" // filler (always 0x00)
4615 * "\x01\x00\x00" // packet length
4616 * "\x00" // packet number
4617 * "\x01" // COM_QUIT command
4618 * };
4619 */
4620
4621
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004622 if (*(args[2])) {
4623 int cur_arg = 2;
4624
4625 while (*(args[cur_arg])) {
4626 if (strcmp(args[cur_arg], "user") == 0) {
4627 char *mysqluser;
4628 int packetlen, reqlen, userlen;
4629
4630 /* suboption header - needs additional argument for it */
4631 if (*(args[cur_arg+1]) == 0) {
4632 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4633 file, linenum, args[0], args[1], args[cur_arg]);
4634 err_code |= ERR_ALERT | ERR_FATAL;
4635 goto out;
4636 }
4637 mysqluser = args[cur_arg + 1];
4638 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004639
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004640 if (*(args[cur_arg+2])) {
4641 if (!strcmp(args[cur_arg+2], "post-41")) {
4642 packetlen = userlen + 7 + 27;
4643 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004644
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004645 free(curproxy->check_req);
4646 curproxy->check_req = (char *)calloc(1, reqlen);
4647 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004648
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004649 snprintf(curproxy->check_req, 4, "%c%c%c",
4650 ((unsigned char) packetlen & 0xff),
4651 ((unsigned char) (packetlen >> 8) & 0xff),
4652 ((unsigned char) (packetlen >> 16) & 0xff));
4653
4654 curproxy->check_req[3] = 1;
4655 curproxy->check_req[5] = 130;
4656 curproxy->check_req[11] = 1;
4657 curproxy->check_req[12] = 33;
4658 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4659 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4660 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4661 cur_arg += 3;
4662 } else {
4663 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4664 err_code |= ERR_ALERT | ERR_FATAL;
4665 goto out;
4666 }
4667 } else {
4668 packetlen = userlen + 7;
4669 reqlen = packetlen + 9;
4670
4671 free(curproxy->check_req);
4672 curproxy->check_req = (char *)calloc(1, reqlen);
4673 curproxy->check_len = reqlen;
4674
4675 snprintf(curproxy->check_req, 4, "%c%c%c",
4676 ((unsigned char) packetlen & 0xff),
4677 ((unsigned char) (packetlen >> 8) & 0xff),
4678 ((unsigned char) (packetlen >> 16) & 0xff));
4679
4680 curproxy->check_req[3] = 1;
4681 curproxy->check_req[5] = 128;
4682 curproxy->check_req[8] = 1;
4683 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4684 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4685 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4686 cur_arg += 2;
4687 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004688 } else {
4689 /* unknown suboption - catchall */
4690 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4691 file, linenum, args[0], args[1]);
4692 err_code |= ERR_ALERT | ERR_FATAL;
4693 goto out;
4694 }
4695 } /* end while loop */
4696 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004697 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004698 else if (!strcmp(args[1], "ldap-check")) {
4699 /* use LDAP request to check servers' health */
4700 free(curproxy->check_req);
4701 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004702 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004703 curproxy->options2 |= PR_O2_LDAP_CHK;
4704
4705 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
4706 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
4707 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004708 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4709 goto out;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004710 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004711 else if (!strcmp(args[1], "tcp-check")) {
4712 /* use raw TCPCHK send/expect to check servers' health */
4713 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4714 err_code |= ERR_WARN;
4715
4716 free(curproxy->check_req);
4717 curproxy->check_req = NULL;
4718 curproxy->options2 &= ~PR_O2_CHK_ANY;
4719 curproxy->options2 |= PR_O2_TCPCHK_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004720 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4721 goto out;
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004722 }
Simon Horman98637e52014-06-20 12:30:16 +09004723 else if (!strcmp(args[1], "external-check")) {
4724 /* excute an external command to check servers' health */
4725 free(curproxy->check_req);
4726 curproxy->check_req = NULL;
4727 curproxy->options2 &= ~PR_O2_CHK_ANY;
4728 curproxy->options2 |= PR_O2_EXT_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004729 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4730 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09004731 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004732 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004733 int cur_arg;
4734
4735 /* insert x-forwarded-for field, but not for the IP address listed as an except.
4736 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004737 */
Ross Westaf72a1d2008-08-03 10:51:45 +02004738
Willy Tarreau87cf5142011-08-19 22:57:24 +02004739 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02004740
4741 free(curproxy->fwdfor_hdr_name);
4742 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
4743 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
4744
4745 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
4746 cur_arg = 2;
4747 while (*(args[cur_arg])) {
4748 if (!strcmp(args[cur_arg], "except")) {
4749 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004750 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004751 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4752 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004753 err_code |= ERR_ALERT | ERR_FATAL;
4754 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004755 }
4756 /* flush useless bits */
4757 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02004758 cur_arg += 2;
4759 } else if (!strcmp(args[cur_arg], "header")) {
4760 /* suboption header - needs additional argument for it */
4761 if (*(args[cur_arg+1]) == 0) {
4762 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4763 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004764 err_code |= ERR_ALERT | ERR_FATAL;
4765 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02004766 }
4767 free(curproxy->fwdfor_hdr_name);
4768 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
4769 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
4770 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02004771 } else if (!strcmp(args[cur_arg], "if-none")) {
4772 curproxy->options &= ~PR_O_FF_ALWAYS;
4773 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004774 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02004775 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02004776 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02004777 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004778 err_code |= ERR_ALERT | ERR_FATAL;
4779 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004780 }
Ross Westaf72a1d2008-08-03 10:51:45 +02004781 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004782 }
Maik Broemme2850cb42009-04-17 18:53:21 +02004783 else if (!strcmp(args[1], "originalto")) {
4784 int cur_arg;
4785
4786 /* insert x-original-to field, but not for the IP address listed as an except.
4787 * set default options (ie: bitfield, header name, etc)
4788 */
4789
4790 curproxy->options |= PR_O_ORGTO;
4791
4792 free(curproxy->orgto_hdr_name);
4793 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
4794 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
4795
Willy Tarreau87cf5142011-08-19 22:57:24 +02004796 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02004797 cur_arg = 2;
4798 while (*(args[cur_arg])) {
4799 if (!strcmp(args[cur_arg], "except")) {
4800 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004801 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 +02004802 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4803 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004804 err_code |= ERR_ALERT | ERR_FATAL;
4805 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004806 }
4807 /* flush useless bits */
4808 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
4809 cur_arg += 2;
4810 } else if (!strcmp(args[cur_arg], "header")) {
4811 /* suboption header - needs additional argument for it */
4812 if (*(args[cur_arg+1]) == 0) {
4813 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4814 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004815 err_code |= ERR_ALERT | ERR_FATAL;
4816 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004817 }
4818 free(curproxy->orgto_hdr_name);
4819 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
4820 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
4821 cur_arg += 2;
4822 } else {
4823 /* unknown suboption - catchall */
4824 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
4825 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004826 err_code |= ERR_ALERT | ERR_FATAL;
4827 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004828 }
4829 } /* end while loop */
4830 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004831 else {
4832 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004833 err_code |= ERR_ALERT | ERR_FATAL;
4834 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004835 }
Willy Tarreau93893792009-07-23 13:19:11 +02004836 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004837 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004838 else if (!strcmp(args[0], "default_backend")) {
4839 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004840 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004841
4842 if (*(args[1]) == 0) {
4843 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004844 err_code |= ERR_ALERT | ERR_FATAL;
4845 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004846 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004847 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004848 curproxy->defbe.name = strdup(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02004849
4850 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
4851 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004852 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004853 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01004854 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004855 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004856
Willy Tarreaua3c504c2014-04-28 22:37:32 +02004857 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
4858 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 +01004859 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004860 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004861 /* enable reconnections to dispatch */
4862 curproxy->options |= PR_O_REDISP;
William Lallemanddf1425a2015-04-28 20:17:49 +02004863
4864 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
4865 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004866 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004867 else if (!strcmp(args[0], "http-check")) {
4868 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004869 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01004870
4871 if (strcmp(args[1], "disable-on-404") == 0) {
4872 /* enable a graceful server shutdown on an HTTP 404 response */
4873 curproxy->options |= PR_O_DISABLE404;
William Lallemanddf1425a2015-04-28 20:17:49 +02004874 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4875 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004876 }
Willy Tarreauef781042010-01-27 11:53:01 +01004877 else if (strcmp(args[1], "send-state") == 0) {
4878 /* enable emission of the apparent state of a server in HTTP checks */
4879 curproxy->options2 |= PR_O2_CHK_SNDST;
William Lallemanddf1425a2015-04-28 20:17:49 +02004880 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4881 goto out;
Willy Tarreauef781042010-01-27 11:53:01 +01004882 }
Willy Tarreaubd741542010-03-16 18:46:54 +01004883 else if (strcmp(args[1], "expect") == 0) {
4884 const char *ptr_arg;
4885 int cur_arg;
4886
4887 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4888 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4889 err_code |= ERR_ALERT | ERR_FATAL;
4890 goto out;
4891 }
4892
4893 cur_arg = 2;
4894 /* consider exclamation marks, sole or at the beginning of a word */
4895 while (*(ptr_arg = args[cur_arg])) {
4896 while (*ptr_arg == '!') {
4897 curproxy->options2 ^= PR_O2_EXP_INV;
4898 ptr_arg++;
4899 }
4900 if (*ptr_arg)
4901 break;
4902 cur_arg++;
4903 }
4904 /* now ptr_arg points to the beginning of a word past any possible
4905 * exclamation mark, and cur_arg is the argument which holds this word.
4906 */
4907 if (strcmp(ptr_arg, "status") == 0) {
4908 if (!*(args[cur_arg + 1])) {
4909 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4910 file, linenum, args[0], args[1], ptr_arg);
4911 err_code |= ERR_ALERT | ERR_FATAL;
4912 goto out;
4913 }
4914 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004915 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004916 curproxy->expect_str = strdup(args[cur_arg + 1]);
4917 }
4918 else if (strcmp(ptr_arg, "string") == 0) {
4919 if (!*(args[cur_arg + 1])) {
4920 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4921 file, linenum, args[0], args[1], ptr_arg);
4922 err_code |= ERR_ALERT | ERR_FATAL;
4923 goto out;
4924 }
4925 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004926 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004927 curproxy->expect_str = strdup(args[cur_arg + 1]);
4928 }
4929 else if (strcmp(ptr_arg, "rstatus") == 0) {
4930 if (!*(args[cur_arg + 1])) {
4931 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4932 file, linenum, args[0], args[1], ptr_arg);
4933 err_code |= ERR_ALERT | ERR_FATAL;
4934 goto out;
4935 }
4936 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004937 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004938 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004939 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004940 free(curproxy->expect_regex);
4941 curproxy->expect_regex = NULL;
4942 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004943 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004944 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4945 error = NULL;
4946 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4947 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4948 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4949 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004950 err_code |= ERR_ALERT | ERR_FATAL;
4951 goto out;
4952 }
4953 }
4954 else if (strcmp(ptr_arg, "rstring") == 0) {
4955 if (!*(args[cur_arg + 1])) {
4956 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4957 file, linenum, args[0], args[1], ptr_arg);
4958 err_code |= ERR_ALERT | ERR_FATAL;
4959 goto out;
4960 }
4961 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004962 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004963 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004964 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004965 free(curproxy->expect_regex);
4966 curproxy->expect_regex = NULL;
4967 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004968 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004969 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4970 error = NULL;
4971 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4972 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4973 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4974 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004975 err_code |= ERR_ALERT | ERR_FATAL;
4976 goto out;
4977 }
4978 }
4979 else {
4980 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
4981 file, linenum, args[0], args[1], ptr_arg);
4982 err_code |= ERR_ALERT | ERR_FATAL;
4983 goto out;
4984 }
4985 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004986 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004987 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 +02004988 err_code |= ERR_ALERT | ERR_FATAL;
4989 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004990 }
4991 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004992 else if (!strcmp(args[0], "tcp-check")) {
4993 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4994 err_code |= ERR_WARN;
4995
Baptiste Assmann22b09d22015-05-01 08:03:04 +02004996 if (strcmp(args[1], "comment") == 0) {
4997 int cur_arg;
4998 struct tcpcheck_rule *tcpcheck;
4999
5000 cur_arg = 1;
5001 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5002 tcpcheck->action = TCPCHK_ACT_COMMENT;
5003
5004 if (!*args[cur_arg + 1]) {
5005 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5006 file, linenum, args[cur_arg]);
5007 err_code |= ERR_ALERT | ERR_FATAL;
5008 goto out;
5009 }
5010
5011 tcpcheck->comment = strdup(args[cur_arg + 1]);
5012
5013 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
William Lallemanddf1425a2015-04-28 20:17:49 +02005014 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
5015 goto out;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005016 }
5017 else if (strcmp(args[1], "connect") == 0) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005018 const char *ptr_arg;
5019 int cur_arg;
5020 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005021
5022 /* check if first rule is also a 'connect' action */
Willy Tarreau5581c272015-05-13 12:24:53 +02005023 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
5024 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
5025 tcpcheck->action == TCPCHK_ACT_COMMENT) {
5026 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
5027 }
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005028
Willy Tarreau5581c272015-05-13 12:24:53 +02005029 if (&tcpcheck->list != &curproxy->tcpcheck_rules
5030 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
5031 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
5032 file, linenum);
5033 err_code |= ERR_ALERT | ERR_FATAL;
5034 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005035 }
5036
5037 cur_arg = 2;
5038 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5039 tcpcheck->action = TCPCHK_ACT_CONNECT;
5040
5041 /* parsing each parameters to fill up the rule */
5042 while (*(ptr_arg = args[cur_arg])) {
5043 /* tcp port */
5044 if (strcmp(args[cur_arg], "port") == 0) {
5045 if ( (atol(args[cur_arg + 1]) > 65535) ||
5046 (atol(args[cur_arg + 1]) < 1) ){
5047 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
5048 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
5049 err_code |= ERR_ALERT | ERR_FATAL;
5050 goto out;
5051 }
5052 tcpcheck->port = atol(args[cur_arg + 1]);
5053 cur_arg += 2;
5054 }
5055 /* send proxy protocol */
5056 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
5057 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
5058 cur_arg++;
5059 }
5060#ifdef USE_OPENSSL
5061 else if (strcmp(args[cur_arg], "ssl") == 0) {
5062 curproxy->options |= PR_O_TCPCHK_SSL;
5063 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
5064 cur_arg++;
5065 }
5066#endif /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005067 /* comment for this tcpcheck line */
5068 else if (strcmp(args[cur_arg], "comment") == 0) {
5069 if (!*args[cur_arg + 1]) {
5070 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5071 file, linenum, args[cur_arg]);
5072 err_code |= ERR_ALERT | ERR_FATAL;
5073 goto out;
5074 }
5075 tcpcheck->comment = strdup(args[cur_arg + 1]);
5076 cur_arg += 2;
5077 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005078 else {
5079#ifdef USE_OPENSSL
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005080 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 +01005081#else /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005082 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 +01005083#endif /* USE_OPENSSL */
5084 file, linenum, args[0], args[1], args[cur_arg]);
5085 err_code |= ERR_ALERT | ERR_FATAL;
5086 goto out;
5087 }
5088
5089 }
5090
5091 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5092 }
5093 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005094 if (! *(args[2]) ) {
5095 /* SEND string expected */
5096 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
5097 file, linenum, args[0], args[1], args[2]);
5098 err_code |= ERR_ALERT | ERR_FATAL;
5099 goto out;
5100 } else {
5101 struct tcpcheck_rule *tcpcheck;
5102
5103 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5104
5105 tcpcheck->action = TCPCHK_ACT_SEND;
5106 tcpcheck->string_len = strlen(args[2]);
5107 tcpcheck->string = strdup(args[2]);
5108 tcpcheck->expect_regex = NULL;
5109
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005110 /* comment for this tcpcheck line */
5111 if (strcmp(args[3], "comment") == 0) {
5112 if (!*args[4]) {
5113 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5114 file, linenum, args[3]);
5115 err_code |= ERR_ALERT | ERR_FATAL;
5116 goto out;
5117 }
5118 tcpcheck->comment = strdup(args[4]);
5119 }
5120
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005121 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5122 }
5123 }
5124 else if (strcmp(args[1], "send-binary") == 0) {
5125 if (! *(args[2]) ) {
5126 /* SEND binary string expected */
5127 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
5128 file, linenum, args[0], args[1], args[2]);
5129 err_code |= ERR_ALERT | ERR_FATAL;
5130 goto out;
5131 } else {
5132 struct tcpcheck_rule *tcpcheck;
5133 char *err = NULL;
5134
5135 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5136
5137 tcpcheck->action = TCPCHK_ACT_SEND;
5138 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5139 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5140 file, linenum, args[0], args[1], args[2], err);
5141 err_code |= ERR_ALERT | ERR_FATAL;
5142 goto out;
5143 }
5144 tcpcheck->expect_regex = NULL;
5145
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005146 /* comment for this tcpcheck line */
5147 if (strcmp(args[3], "comment") == 0) {
5148 if (!*args[4]) {
5149 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5150 file, linenum, args[3]);
5151 err_code |= ERR_ALERT | ERR_FATAL;
5152 goto out;
5153 }
5154 tcpcheck->comment = strdup(args[4]);
5155 }
5156
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005157 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5158 }
5159 }
5160 else if (strcmp(args[1], "expect") == 0) {
5161 const char *ptr_arg;
5162 int cur_arg;
5163 int inverse = 0;
5164
5165 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5166 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5167 err_code |= ERR_ALERT | ERR_FATAL;
5168 goto out;
5169 }
5170
5171 cur_arg = 2;
5172 /* consider exclamation marks, sole or at the beginning of a word */
5173 while (*(ptr_arg = args[cur_arg])) {
5174 while (*ptr_arg == '!') {
5175 inverse = !inverse;
5176 ptr_arg++;
5177 }
5178 if (*ptr_arg)
5179 break;
5180 cur_arg++;
5181 }
5182 /* now ptr_arg points to the beginning of a word past any possible
5183 * exclamation mark, and cur_arg is the argument which holds this word.
5184 */
5185 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005186 struct tcpcheck_rule *tcpcheck;
5187 char *err = NULL;
5188
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005189 if (!*(args[cur_arg + 1])) {
5190 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
5191 file, linenum, args[0], args[1], ptr_arg);
5192 err_code |= ERR_ALERT | ERR_FATAL;
5193 goto out;
5194 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005195
5196 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5197
5198 tcpcheck->action = TCPCHK_ACT_EXPECT;
5199 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5200 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5201 file, linenum, args[0], args[1], args[2], err);
5202 err_code |= ERR_ALERT | ERR_FATAL;
5203 goto out;
5204 }
5205 tcpcheck->expect_regex = NULL;
5206 tcpcheck->inverse = inverse;
5207
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005208 /* tcpcheck comment */
5209 cur_arg += 2;
5210 if (strcmp(args[cur_arg], "comment") == 0) {
5211 if (!*args[cur_arg + 1]) {
5212 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5213 file, linenum, args[cur_arg + 1]);
5214 err_code |= ERR_ALERT | ERR_FATAL;
5215 goto out;
5216 }
5217 tcpcheck->comment = strdup(args[cur_arg + 1]);
5218 }
5219
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005220 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5221 }
5222 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005223 struct tcpcheck_rule *tcpcheck;
5224
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005225 if (!*(args[cur_arg + 1])) {
5226 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5227 file, linenum, args[0], args[1], ptr_arg);
5228 err_code |= ERR_ALERT | ERR_FATAL;
5229 goto out;
5230 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005231
5232 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5233
5234 tcpcheck->action = TCPCHK_ACT_EXPECT;
5235 tcpcheck->string_len = strlen(args[cur_arg + 1]);
5236 tcpcheck->string = strdup(args[cur_arg + 1]);
5237 tcpcheck->expect_regex = NULL;
5238 tcpcheck->inverse = inverse;
5239
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005240 /* tcpcheck comment */
5241 cur_arg += 2;
5242 if (strcmp(args[cur_arg], "comment") == 0) {
5243 if (!*args[cur_arg + 1]) {
5244 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5245 file, linenum, args[cur_arg + 1]);
5246 err_code |= ERR_ALERT | ERR_FATAL;
5247 goto out;
5248 }
5249 tcpcheck->comment = strdup(args[cur_arg + 1]);
5250 }
5251
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005252 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5253 }
5254 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005255 struct tcpcheck_rule *tcpcheck;
5256
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005257 if (!*(args[cur_arg + 1])) {
5258 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5259 file, linenum, args[0], args[1], ptr_arg);
5260 err_code |= ERR_ALERT | ERR_FATAL;
5261 goto out;
5262 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005263
5264 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5265
5266 tcpcheck->action = TCPCHK_ACT_EXPECT;
5267 tcpcheck->string_len = 0;
5268 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005269 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
5270 error = NULL;
5271 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
5272 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5273 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5274 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005275 err_code |= ERR_ALERT | ERR_FATAL;
5276 goto out;
5277 }
5278 tcpcheck->inverse = inverse;
5279
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005280 /* tcpcheck comment */
5281 cur_arg += 2;
5282 if (strcmp(args[cur_arg], "comment") == 0) {
5283 if (!*args[cur_arg + 1]) {
5284 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5285 file, linenum, args[cur_arg + 1]);
5286 err_code |= ERR_ALERT | ERR_FATAL;
5287 goto out;
5288 }
5289 tcpcheck->comment = strdup(args[cur_arg + 1]);
5290 }
5291
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005292 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5293 }
5294 else {
5295 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
5296 file, linenum, args[0], args[1], ptr_arg);
5297 err_code |= ERR_ALERT | ERR_FATAL;
5298 goto out;
5299 }
5300 }
5301 else {
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005302 Alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005303 err_code |= ERR_ALERT | ERR_FATAL;
5304 goto out;
5305 }
5306 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01005307 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02005308 if (curproxy == &defproxy) {
5309 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005310 err_code |= ERR_ALERT | ERR_FATAL;
5311 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02005312 }
5313
Willy Tarreaub80c2302007-11-30 20:51:32 +01005314 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005315 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005316
5317 if (strcmp(args[1], "fail") == 0) {
5318 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01005319 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01005320 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
5321 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005322 err_code |= ERR_ALERT | ERR_FATAL;
5323 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005324 }
5325
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005326 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
5327 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
5328 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005329 err_code |= ERR_ALERT | ERR_FATAL;
5330 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005331 }
5332 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
5333 }
5334 else {
5335 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005336 err_code |= ERR_ALERT | ERR_FATAL;
5337 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005338 }
5339 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005340#ifdef TPROXY
5341 else if (!strcmp(args[0], "transparent")) {
5342 /* enable transparent proxy connections */
5343 curproxy->options |= PR_O_TRANSP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005344 if (alertif_too_many_args(0, file, linenum, args, &err_code))
5345 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005346 }
5347#endif
5348 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005349 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005350 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005351
Willy Tarreaubaaee002006-06-26 02:48:02 +02005352 if (*(args[1]) == 0) {
5353 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005354 err_code |= ERR_ALERT | ERR_FATAL;
5355 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005356 }
5357 curproxy->maxconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005358 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5359 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005360 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005361 else if (!strcmp(args[0], "backlog")) { /* backlog */
5362 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005363 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005364
5365 if (*(args[1]) == 0) {
5366 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005367 err_code |= ERR_ALERT | ERR_FATAL;
5368 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005369 }
5370 curproxy->backlog = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005371 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5372 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005373 }
Willy Tarreau86034312006-12-29 00:10:33 +01005374 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005375 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005376 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005377
Willy Tarreau86034312006-12-29 00:10:33 +01005378 if (*(args[1]) == 0) {
5379 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005380 err_code |= ERR_ALERT | ERR_FATAL;
5381 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005382 }
5383 curproxy->fullconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005384 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5385 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005386 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005387 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
5388 if (*(args[1]) == 0) {
5389 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005390 err_code |= ERR_ALERT | ERR_FATAL;
5391 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005392 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005393 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
5394 if (err) {
5395 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
5396 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02005397 err_code |= ERR_ALERT | ERR_FATAL;
5398 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005399 }
5400 curproxy->grace = val;
William Lallemanddf1425a2015-04-28 20:17:49 +02005401 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5402 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005403 }
5404 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01005405 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005406 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005407 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005408
Willy Tarreaubaaee002006-06-26 02:48:02 +02005409 if (curproxy == &defproxy) {
5410 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005411 err_code |= ERR_ALERT | ERR_FATAL;
5412 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005413 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005414 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005415 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005416
Willy Tarreau902636f2013-03-10 19:44:48 +01005417 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005418 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005419 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005420 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005421 goto out;
5422 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005423
5424 proto = protocol_by_family(sk->ss_family);
5425 if (!proto || !proto->connect) {
5426 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5427 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005428 err_code |= ERR_ALERT | ERR_FATAL;
5429 goto out;
5430 }
5431
5432 if (port1 != port2) {
5433 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5434 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005435 err_code |= ERR_ALERT | ERR_FATAL;
5436 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005437 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005438
5439 if (!port1) {
5440 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5441 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005442 err_code |= ERR_ALERT | ERR_FATAL;
5443 goto out;
5444 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005445
William Lallemanddf1425a2015-04-28 20:17:49 +02005446 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5447 goto out;
5448
Willy Tarreaud5191e72010-02-09 20:50:45 +01005449 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005450 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005451 }
5452 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005453 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005454 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005455
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005456 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5457 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005458 err_code |= ERR_ALERT | ERR_FATAL;
5459 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005460 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005461 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005462 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005463 /**
5464 * The syntax for hash-type config element is
5465 * hash-type {map-based|consistent} [[<algo>] avalanche]
5466 *
5467 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5468 */
5469 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005470
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005471 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5472 err_code |= ERR_WARN;
5473
5474 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005475 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5476 }
5477 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005478 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5479 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005480 else if (strcmp(args[1], "avalanche") == 0) {
5481 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]);
5482 err_code |= ERR_ALERT | ERR_FATAL;
5483 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005484 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005485 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005486 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005487 err_code |= ERR_ALERT | ERR_FATAL;
5488 goto out;
5489 }
Bhaskar98634f02013-10-29 23:30:51 -04005490
5491 /* set the hash function to use */
5492 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005493 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005494 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005495
5496 /* if consistent with no argument, then avalanche modifier is also applied */
5497 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5498 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005499 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005500 /* set the hash function */
5501 if (!strcmp(args[2], "sdbm")) {
5502 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5503 }
5504 else if (!strcmp(args[2], "djb2")) {
5505 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005506 }
5507 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005508 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005509 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005510 else if (!strcmp(args[2], "crc32")) {
5511 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5512 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005513 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005514 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 -05005515 err_code |= ERR_ALERT | ERR_FATAL;
5516 goto out;
5517 }
5518
5519 /* set the hash modifier */
5520 if (!strcmp(args[3], "avalanche")) {
5521 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5522 }
5523 else if (*args[3]) {
5524 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5525 err_code |= ERR_ALERT | ERR_FATAL;
5526 goto out;
5527 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005528 }
William Lallemanda73203e2012-03-12 12:48:57 +01005529 }
William Lallemanda73203e2012-03-12 12:48:57 +01005530 else if (strcmp(args[0], "unique-id-format") == 0) {
5531 if (!*(args[1])) {
5532 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5533 err_code |= ERR_ALERT | ERR_FATAL;
5534 goto out;
5535 }
William Lallemand3203ff42012-11-11 17:30:56 +01005536 if (*(args[2])) {
5537 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5538 err_code |= ERR_ALERT | ERR_FATAL;
5539 goto out;
5540 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005541 free(curproxy->conf.uniqueid_format_string);
5542 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005543
Willy Tarreau62a61232013-04-12 18:13:46 +02005544 free(curproxy->conf.uif_file);
5545 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5546 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005547 }
William Lallemanda73203e2012-03-12 12:48:57 +01005548
5549 else if (strcmp(args[0], "unique-id-header") == 0) {
5550 if (!*(args[1])) {
5551 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5552 err_code |= ERR_ALERT | ERR_FATAL;
5553 goto out;
5554 }
5555 free(curproxy->header_unique_id);
5556 curproxy->header_unique_id = strdup(args[1]);
5557 }
5558
William Lallemand723b73a2012-02-08 16:37:49 +01005559 else if (strcmp(args[0], "log-format") == 0) {
5560 if (!*(args[1])) {
5561 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5562 err_code |= ERR_ALERT | ERR_FATAL;
5563 goto out;
5564 }
William Lallemand3203ff42012-11-11 17:30:56 +01005565 if (*(args[2])) {
5566 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5567 err_code |= ERR_ALERT | ERR_FATAL;
5568 goto out;
5569 }
Willy Tarreau196729e2012-05-31 19:30:26 +02005570
Willy Tarreau62a61232013-04-12 18:13:46 +02005571 if (curproxy->conf.logformat_string != default_http_log_format &&
5572 curproxy->conf.logformat_string != default_tcp_log_format &&
5573 curproxy->conf.logformat_string != clf_http_log_format)
5574 free(curproxy->conf.logformat_string);
5575 curproxy->conf.logformat_string = strdup(args[1]);
5576
5577 free(curproxy->conf.lfs_file);
5578 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5579 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005580
5581 /* get a chance to improve log-format error reporting by
5582 * reporting the correct line-number when possible.
5583 */
5584 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5585 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5586 file, linenum, curproxy->id);
5587 err_code |= ERR_WARN;
5588 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005589 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01005590 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
5591 if (*(args[1]) == 0) {
5592 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
5593 err_code |= ERR_ALERT | ERR_FATAL;
5594 goto out;
5595 }
5596 free(curproxy->log_tag);
5597 curproxy->log_tag = strdup(args[1]);
5598 }
William Lallemand0f99e342011-10-12 17:50:54 +02005599 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
5600 /* delete previous herited or defined syslog servers */
5601 struct logsrv *back;
5602
5603 if (*(args[1]) != 0) {
5604 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
5605 err_code |= ERR_ALERT | ERR_FATAL;
5606 goto out;
5607 }
5608
William Lallemand723b73a2012-02-08 16:37:49 +01005609 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
5610 LIST_DEL(&tmplogsrv->list);
5611 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02005612 }
5613 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005614 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02005615 struct logsrv *logsrv;
5616
Willy Tarreaubaaee002006-06-26 02:48:02 +02005617 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005618 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01005619 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02005620 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01005621 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02005622 LIST_INIT(&node->list);
5623 LIST_ADDQ(&curproxy->logsrvs, &node->list);
5624 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005625 }
5626 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005627 struct sockaddr_storage *sk;
5628 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02005629 int arg = 0;
5630 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02005631
5632 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005633
Willy Tarreau18324f52014-06-27 18:10:07 +02005634 /* just after the address, a length may be specified */
5635 if (strcmp(args[arg+2], "len") == 0) {
5636 len = atoi(args[arg+3]);
5637 if (len < 80 || len > 65535) {
5638 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
5639 file, linenum, args[arg+3]);
5640 err_code |= ERR_ALERT | ERR_FATAL;
5641 goto out;
5642 }
5643 logsrv->maxlen = len;
5644
5645 /* skip these two args */
5646 arg += 2;
5647 }
5648 else
5649 logsrv->maxlen = MAX_SYSLOG_LEN;
5650
5651 if (logsrv->maxlen > global.max_syslog_len) {
5652 global.max_syslog_len = logsrv->maxlen;
5653 logline = realloc(logline, global.max_syslog_len + 1);
5654 }
5655
William Lallemanddf1425a2015-04-28 20:17:49 +02005656 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
5657 goto out;
5658
Willy Tarreau18324f52014-06-27 18:10:07 +02005659 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005660 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005661 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005662 err_code |= ERR_ALERT | ERR_FATAL;
5663 goto out;
5664
Willy Tarreaubaaee002006-06-26 02:48:02 +02005665 }
5666
William Lallemand0f99e342011-10-12 17:50:54 +02005667 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02005668 if (*(args[arg+3])) {
5669 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005670 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005671 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005672 err_code |= ERR_ALERT | ERR_FATAL;
5673 goto out;
5674
Willy Tarreaubaaee002006-06-26 02:48:02 +02005675 }
5676 }
5677
William Lallemand0f99e342011-10-12 17:50:54 +02005678 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02005679 if (*(args[arg+4])) {
5680 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01005681 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005682 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02005683 err_code |= ERR_ALERT | ERR_FATAL;
5684 goto out;
5685
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005686 }
5687 }
5688
Willy Tarreau902636f2013-03-10 19:44:48 +01005689 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005690 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005691 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005692 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005693 goto out;
5694 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005695
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005696 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005697
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005698 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005699 if (port1 != port2) {
5700 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5701 file, linenum, args[0], args[1]);
5702 err_code |= ERR_ALERT | ERR_FATAL;
5703 goto out;
5704 }
5705
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005706 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02005707 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005708 }
William Lallemand0f99e342011-10-12 17:50:54 +02005709
5710 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005711 }
5712 else {
5713 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
5714 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005715 err_code |= ERR_ALERT | ERR_FATAL;
5716 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005717 }
5718 }
5719 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005720 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005721 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01005722 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005723 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005724
Willy Tarreau977b8e42006-12-29 14:19:17 +01005725 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005726 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005727
Willy Tarreaubaaee002006-06-26 02:48:02 +02005728 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005729 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
5730 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005731 err_code |= ERR_ALERT | ERR_FATAL;
5732 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005733 }
Willy Tarreau368480c2009-03-01 08:27:21 +01005734
5735 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01005736 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5737 free(curproxy->conn_src.iface_name);
5738 curproxy->conn_src.iface_name = NULL;
5739 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01005740
Willy Tarreau902636f2013-03-10 19:44:48 +01005741 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005742 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005743 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005744 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005745 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005746 goto out;
5747 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005748
5749 proto = protocol_by_family(sk->ss_family);
5750 if (!proto || !proto->connect) {
5751 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005752 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005753 err_code |= ERR_ALERT | ERR_FATAL;
5754 goto out;
5755 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005756
5757 if (port1 != port2) {
5758 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5759 file, linenum, args[0], args[1]);
5760 err_code |= ERR_ALERT | ERR_FATAL;
5761 goto out;
5762 }
5763
Willy Tarreauef9a3602012-12-08 22:29:20 +01005764 curproxy->conn_src.source_addr = *sk;
5765 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005766
5767 cur_arg = 2;
5768 while (*(args[cur_arg])) {
5769 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02005770#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
5771#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreau9cf8d3f2014-05-09 22:56:10 +02005772 if (!is_inet_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005773 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5774 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005775 err_code |= ERR_ALERT | ERR_FATAL;
5776 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005777 }
5778#endif
5779 if (!*args[cur_arg + 1]) {
5780 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5781 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005782 err_code |= ERR_ALERT | ERR_FATAL;
5783 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005784 }
5785
5786 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005787 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5788 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005789 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005790 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5791 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005792 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5793 char *name, *end;
5794
5795 name = args[cur_arg+1] + 7;
5796 while (isspace(*name))
5797 name++;
5798
5799 end = name;
5800 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5801 end++;
5802
Willy Tarreauef9a3602012-12-08 22:29:20 +01005803 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5804 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5805 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5806 curproxy->conn_src.bind_hdr_len = end - name;
5807 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5808 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5809 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005810
5811 /* now look for an occurrence number */
5812 while (isspace(*end))
5813 end++;
5814 if (*end == ',') {
5815 end++;
5816 name = end;
5817 if (*end == '-')
5818 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005819 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005820 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005821 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005822 }
5823
Willy Tarreauef9a3602012-12-08 22:29:20 +01005824 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005825 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5826 " occurrences values smaller than %d.\n",
5827 file, linenum, MAX_HDR_HISTORY);
5828 err_code |= ERR_ALERT | ERR_FATAL;
5829 goto out;
5830 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005831 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005832 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005833
Willy Tarreau902636f2013-03-10 19:44:48 +01005834 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005835 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005836 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005837 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005838 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005839 goto out;
5840 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005841
5842 proto = protocol_by_family(sk->ss_family);
5843 if (!proto || !proto->connect) {
5844 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5845 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005846 err_code |= ERR_ALERT | ERR_FATAL;
5847 goto out;
5848 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005849
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005850 if (port1 != port2) {
5851 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5852 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005853 err_code |= ERR_ALERT | ERR_FATAL;
5854 goto out;
5855 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005856 curproxy->conn_src.tproxy_addr = *sk;
5857 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005858 }
5859 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005860#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005861 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005862#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005863#else /* no TPROXY support */
5864 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005865 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005866 err_code |= ERR_ALERT | ERR_FATAL;
5867 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005868#endif
5869 cur_arg += 2;
5870 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005871 }
5872
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005873 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5874#ifdef SO_BINDTODEVICE
5875 if (!*args[cur_arg + 1]) {
5876 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5877 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005878 err_code |= ERR_ALERT | ERR_FATAL;
5879 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005880 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005881 free(curproxy->conn_src.iface_name);
5882 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5883 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005884 global.last_checks |= LSTCHK_NETADM;
5885#else
5886 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5887 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005888 err_code |= ERR_ALERT | ERR_FATAL;
5889 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005890#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005891 cur_arg += 2;
5892 continue;
5893 }
5894 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005895 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005896 err_code |= ERR_ALERT | ERR_FATAL;
5897 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005898 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005899 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005900 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5901 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5902 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005903 err_code |= ERR_ALERT | ERR_FATAL;
5904 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005905 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005906 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005907 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005908 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5909 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005910 err_code |= ERR_ALERT | ERR_FATAL;
5911 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005912 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005913
5914 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005915 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005916 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005917 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005918 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005919 }
5920 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005921 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005922 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005923 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005924 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005925 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005926 }
5927 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005928 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005929 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005930 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005931 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005932 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005933 }
5934 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005935 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005936 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005937 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005938 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005939 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005940 }
5941 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005942 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005943 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005944 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005945 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005946 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005947 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005948 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005949 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005950 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005951 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005952 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005953 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005954 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005955 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005956 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005957 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5958 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005959 err_code |= ERR_ALERT | ERR_FATAL;
5960 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005961 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005962
5963 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005964 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005965 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005966 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005967 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005968 }
5969 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005970 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005971 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005972 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005973 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005974 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005975 }
5976 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005977 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005978 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005979 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005980 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005981 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005982 }
5983 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005984 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005985 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005986 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005987 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005988 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005989 }
5990 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005991 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005992 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005993 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005994 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005995 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005996 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005997 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005998 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005999 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006000 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006001 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006002 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006003 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006004 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006005 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006006
Willy Tarreaubaaee002006-06-26 02:48:02 +02006007 if (curproxy == &defproxy) {
6008 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006009 err_code |= ERR_ALERT | ERR_FATAL;
6010 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006011 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006012 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006013 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006014
Willy Tarreaubaaee002006-06-26 02:48:02 +02006015 if (*(args[1]) == 0) {
6016 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006017 err_code |= ERR_ALERT | ERR_FATAL;
6018 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006019 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006020
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006021 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006022 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6023 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6024 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006025 err_code |= ERR_ALERT | ERR_FATAL;
6026 goto out;
6027 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006028 err_code |= warnif_cond_conflicts(cond,
6029 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6030 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006031 }
6032 else if (*args[2]) {
6033 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6034 file, linenum, args[0], args[2]);
6035 err_code |= ERR_ALERT | ERR_FATAL;
6036 goto out;
6037 }
6038
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006039 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006040 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006041 wl->s = strdup(args[1]);
6042 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02006043 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006044 }
6045 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006046 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006047 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6048 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006049 err_code |= ERR_ALERT | ERR_FATAL;
6050 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006051 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006052
Willy Tarreauade5ec42010-01-28 19:33:49 +01006053 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006054 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006055 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006056 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006057 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006058 }
6059 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006060 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006061 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006062 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006063 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006064 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006065 }
6066 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006067 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006068 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006069 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006070 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006071 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006072 }
6073 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006074 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006075 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6076 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006077 err_code |= ERR_ALERT | ERR_FATAL;
6078 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006079 }
6080
Willy Tarreauade5ec42010-01-28 19:33:49 +01006081 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006082 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006083 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006084 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006085 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006086 }
6087 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006088 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006089 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006090 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006091 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006092 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006093 }
6094 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006095 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006096 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006097 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006098 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006099 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006100 }
6101 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006102 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006103
Willy Tarreaubaaee002006-06-26 02:48:02 +02006104 if (curproxy == &defproxy) {
6105 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006106 err_code |= ERR_ALERT | ERR_FATAL;
6107 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006108 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006109 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006110 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006111
Willy Tarreaubaaee002006-06-26 02:48:02 +02006112 if (*(args[1]) == 0) {
6113 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006114 err_code |= ERR_ALERT | ERR_FATAL;
6115 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006116 }
6117
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006118 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006119 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6120 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6121 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006122 err_code |= ERR_ALERT | ERR_FATAL;
6123 goto out;
6124 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006125 err_code |= warnif_cond_conflicts(cond,
6126 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
6127 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006128 }
6129 else if (*args[2]) {
6130 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6131 file, linenum, args[0], args[2]);
6132 err_code |= ERR_ALERT | ERR_FATAL;
6133 goto out;
6134 }
6135
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006136 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006137 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006138 wl->s = strdup(args[1]);
6139 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006140 }
6141 else if (!strcmp(args[0], "errorloc") ||
6142 !strcmp(args[0], "errorloc302") ||
6143 !strcmp(args[0], "errorloc303")) { /* error location */
6144 int errnum, errlen;
6145 char *err;
6146
Willy Tarreau977b8e42006-12-29 14:19:17 +01006147 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006148 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006149
Willy Tarreaubaaee002006-06-26 02:48:02 +02006150 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006151 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006152 err_code |= ERR_ALERT | ERR_FATAL;
6153 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006154 }
6155
6156 errnum = atol(args[1]);
6157 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006158 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
6159 err = malloc(errlen);
6160 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006161 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006162 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
6163 err = malloc(errlen);
6164 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006165 }
6166
Willy Tarreau0f772532006-12-23 20:51:41 +01006167 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6168 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006169 chunk_destroy(&curproxy->errmsg[rc]);
6170 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01006171 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006172 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006173 }
Willy Tarreau0f772532006-12-23 20:51:41 +01006174
6175 if (rc >= HTTP_ERR_SIZE) {
6176 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
6177 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006178 free(err);
6179 }
6180 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02006181 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
6182 int errnum, errlen, fd;
6183 char *err;
6184 struct stat stat;
6185
6186 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006187 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006188
6189 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006190 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006191 err_code |= ERR_ALERT | ERR_FATAL;
6192 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006193 }
6194
6195 fd = open(args[2], O_RDONLY);
6196 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
6197 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
6198 file, linenum, args[2], args[1]);
6199 if (fd >= 0)
6200 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02006201 err_code |= ERR_ALERT | ERR_FATAL;
6202 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006203 }
6204
Willy Tarreau27a674e2009-08-17 07:23:33 +02006205 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02006206 errlen = stat.st_size;
6207 } else {
6208 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02006209 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02006210 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02006211 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006212 }
6213
6214 err = malloc(errlen); /* malloc() must succeed during parsing */
6215 errnum = read(fd, err, errlen);
6216 if (errnum != errlen) {
6217 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
6218 file, linenum, args[2], args[1]);
6219 close(fd);
6220 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02006221 err_code |= ERR_ALERT | ERR_FATAL;
6222 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006223 }
6224 close(fd);
6225
6226 errnum = atol(args[1]);
6227 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6228 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006229 chunk_destroy(&curproxy->errmsg[rc]);
6230 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02006231 break;
6232 }
6233 }
6234
6235 if (rc >= HTTP_ERR_SIZE) {
6236 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
6237 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02006238 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006239 free(err);
6240 }
6241 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006242 else if (!strcmp(args[0], "compression")) {
6243 struct comp *comp;
6244 if (curproxy->comp == NULL) {
6245 comp = calloc(1, sizeof(struct comp));
6246 curproxy->comp = comp;
6247 } else {
6248 comp = curproxy->comp;
6249 }
6250
6251 if (!strcmp(args[1], "algo")) {
6252 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01006253 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01006254
William Lallemand82fe75c2012-10-23 10:25:10 +02006255 cur_arg = 2;
6256 if (!*args[cur_arg]) {
6257 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
6258 file, linenum, args[0]);
6259 err_code |= ERR_ALERT | ERR_FATAL;
6260 goto out;
6261 }
6262 while (*(args[cur_arg])) {
6263 if (comp_append_algo(comp, args[cur_arg]) < 0) {
6264 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
6265 file, linenum, args[0], args[cur_arg]);
6266 err_code |= ERR_ALERT | ERR_FATAL;
6267 goto out;
6268 }
William Lallemand552df672012-11-07 13:21:47 +01006269 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
6270 curproxy->comp->algos->end(&ctx);
6271 } else {
6272 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
6273 file, linenum, args[0], args[cur_arg]);
6274 err_code |= ERR_ALERT | ERR_FATAL;
6275 goto out;
6276 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006277 cur_arg ++;
6278 continue;
6279 }
6280 }
Willy Tarreau70737d12012-10-27 00:34:28 +02006281 else if (!strcmp(args[1], "offload")) {
6282 comp->offload = 1;
6283 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006284 else if (!strcmp(args[1], "type")) {
6285 int cur_arg;
6286 cur_arg = 2;
6287 if (!*args[cur_arg]) {
6288 Alert("parsing [%s:%d] : '%s' expects <type>\n",
6289 file, linenum, args[0]);
6290 err_code |= ERR_ALERT | ERR_FATAL;
6291 goto out;
6292 }
6293 while (*(args[cur_arg])) {
6294 comp_append_type(comp, args[cur_arg]);
6295 cur_arg ++;
6296 continue;
6297 }
6298 }
6299 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02006300 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02006301 file, linenum, args[0]);
6302 err_code |= ERR_ALERT | ERR_FATAL;
6303 goto out;
6304 }
6305 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006306 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006307 struct cfg_kw_list *kwl;
6308 int index;
6309
6310 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6311 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6312 if (kwl->kw[index].section != CFG_LISTEN)
6313 continue;
6314 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6315 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006316 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006317 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006318 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006319 err_code |= ERR_ALERT | ERR_FATAL;
6320 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006321 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006322 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006323 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006324 err_code |= ERR_WARN;
6325 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006326 }
Willy Tarreau93893792009-07-23 13:19:11 +02006327 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006328 }
6329 }
6330 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006331
Willy Tarreau6daf3432008-01-22 16:44:08 +01006332 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006333 err_code |= ERR_ALERT | ERR_FATAL;
6334 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006335 }
Willy Tarreau93893792009-07-23 13:19:11 +02006336 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006337 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006338 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006339}
6340
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006341int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006342cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
6343{
6344#ifdef CONFIG_HAP_NS
6345 const char *err;
6346 const char *item = args[0];
6347
6348 if (!strcmp(item, "namespace_list")) {
6349 return 0;
6350 }
6351 else if (!strcmp(item, "namespace")) {
6352 size_t idx = 1;
6353 const char *current;
6354 while (*(current = args[idx++])) {
6355 err = invalid_char(current);
6356 if (err) {
6357 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6358 file, linenum, *err, item, current);
6359 return ERR_ALERT | ERR_FATAL;
6360 }
6361
6362 if (netns_store_lookup(current, strlen(current))) {
6363 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
6364 file, linenum, current);
6365 return ERR_ALERT | ERR_FATAL;
6366 }
6367 if (!netns_store_insert(current)) {
6368 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
6369 file, linenum, current);
6370 return ERR_ALERT | ERR_FATAL;
6371 }
6372 }
6373 }
6374
6375 return 0;
6376#else
6377 Alert("parsing [%s:%d]: namespace support is not compiled in.",
6378 file, linenum);
6379 return ERR_ALERT | ERR_FATAL;
6380#endif
6381}
6382
6383int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006384cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6385{
6386
6387 int err_code = 0;
6388 const char *err;
6389
6390 if (!strcmp(args[0], "userlist")) { /* new userlist */
6391 struct userlist *newul;
6392
6393 if (!*args[1]) {
6394 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6395 file, linenum, args[0]);
6396 err_code |= ERR_ALERT | ERR_FATAL;
6397 goto out;
6398 }
William Lallemand6e62fb62015-04-28 16:55:23 +02006399 if (alertif_too_many_args(1, file, linenum, args, &err_code))
6400 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006401
6402 err = invalid_char(args[1]);
6403 if (err) {
6404 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6405 file, linenum, *err, args[0], args[1]);
6406 err_code |= ERR_ALERT | ERR_FATAL;
6407 goto out;
6408 }
6409
6410 for (newul = userlist; newul; newul = newul->next)
6411 if (!strcmp(newul->name, args[1])) {
6412 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6413 file, linenum, args[1]);
6414 err_code |= ERR_WARN;
6415 goto out;
6416 }
6417
6418 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
6419 if (!newul) {
6420 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6421 err_code |= ERR_ALERT | ERR_ABORT;
6422 goto out;
6423 }
6424
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006425 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006426 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006427 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6428 err_code |= ERR_ALERT | ERR_ABORT;
6429 goto out;
6430 }
6431
6432 newul->next = userlist;
6433 userlist = newul;
6434
6435 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006436 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006437 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006438 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006439
6440 if (!*args[1]) {
6441 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6442 file, linenum, args[0]);
6443 err_code |= ERR_ALERT | ERR_FATAL;
6444 goto out;
6445 }
6446
6447 err = invalid_char(args[1]);
6448 if (err) {
6449 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6450 file, linenum, *err, args[0], args[1]);
6451 err_code |= ERR_ALERT | ERR_FATAL;
6452 goto out;
6453 }
6454
William Lallemand4ac9f542015-05-28 18:03:51 +02006455 if (!userlist)
6456 goto out;
6457
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006458 for (ag = userlist->groups; ag; ag = ag->next)
6459 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006460 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6461 file, linenum, args[1], userlist->name);
6462 err_code |= ERR_ALERT;
6463 goto out;
6464 }
6465
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006466 ag = calloc(1, sizeof(*ag));
6467 if (!ag) {
6468 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6469 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006470 goto out;
6471 }
6472
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006473 ag->name = strdup(args[1]);
6474 if (!ag) {
6475 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6476 err_code |= ERR_ALERT | ERR_ABORT;
6477 goto out;
6478 }
6479
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006480 cur_arg = 2;
6481
6482 while (*args[cur_arg]) {
6483 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006484 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006485 cur_arg += 2;
6486 continue;
6487 } else {
6488 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6489 file, linenum, args[0]);
6490 err_code |= ERR_ALERT | ERR_FATAL;
6491 goto out;
6492 }
6493 }
6494
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006495 ag->next = userlist->groups;
6496 userlist->groups = ag;
6497
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006498 } else if (!strcmp(args[0], "user")) { /* new user */
6499 struct auth_users *newuser;
6500 int cur_arg;
6501
6502 if (!*args[1]) {
6503 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6504 file, linenum, args[0]);
6505 err_code |= ERR_ALERT | ERR_FATAL;
6506 goto out;
6507 }
William Lallemand4ac9f542015-05-28 18:03:51 +02006508 if (!userlist)
6509 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006510
6511 for (newuser = userlist->users; newuser; newuser = newuser->next)
6512 if (!strcmp(newuser->user, args[1])) {
6513 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6514 file, linenum, args[1], userlist->name);
6515 err_code |= ERR_ALERT;
6516 goto out;
6517 }
6518
6519 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
6520 if (!newuser) {
6521 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6522 err_code |= ERR_ALERT | ERR_ABORT;
6523 goto out;
6524 }
6525
6526 newuser->user = strdup(args[1]);
6527
6528 newuser->next = userlist->users;
6529 userlist->users = newuser;
6530
6531 cur_arg = 2;
6532
6533 while (*args[cur_arg]) {
6534 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006535#ifdef CONFIG_HAP_CRYPT
6536 if (!crypt("", args[cur_arg + 1])) {
6537 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6538 file, linenum, newuser->user);
6539 err_code |= ERR_ALERT | ERR_FATAL;
6540 goto out;
6541 }
6542#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006543 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6544 file, linenum);
6545 err_code |= ERR_ALERT;
6546#endif
6547 newuser->pass = strdup(args[cur_arg + 1]);
6548 cur_arg += 2;
6549 continue;
6550 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6551 newuser->pass = strdup(args[cur_arg + 1]);
6552 newuser->flags |= AU_O_INSECURE;
6553 cur_arg += 2;
6554 continue;
6555 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006556 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006557 cur_arg += 2;
6558 continue;
6559 } else {
6560 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6561 file, linenum, args[0]);
6562 err_code |= ERR_ALERT | ERR_FATAL;
6563 goto out;
6564 }
6565 }
6566 } else {
6567 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6568 err_code |= ERR_ALERT | ERR_FATAL;
6569 }
6570
6571out:
6572 return err_code;
6573}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006574
6575/*
6576 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006577 * Returns the error code, 0 if OK, or any combination of :
6578 * - ERR_ABORT: must abort ASAP
6579 * - ERR_FATAL: we can continue parsing but not start the service
6580 * - ERR_WARN: a warning has been emitted
6581 * - ERR_ALERT: an alert has been emitted
6582 * Only the two first ones can stop processing, the two others are just
6583 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006584 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006585int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006586{
William Lallemand64e84512015-05-12 14:25:37 +02006587 char *thisline;
6588 int linesize = LINESIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006589 FILE *f;
6590 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02006591 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006592 struct cfg_section *cs = NULL;
6593 struct cfg_section *ics;
William Lallemand64e84512015-05-12 14:25:37 +02006594 int readbytes = 0;
6595
6596 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
William Lallemandb2f07452015-05-12 14:27:13 +02006597 Alert("parsing [%s] : out of memory.\n", file);
William Lallemand64e84512015-05-12 14:25:37 +02006598 return -1;
6599 }
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006600
6601 /* Register internal sections */
6602 if (!cfg_register_section("listen", cfg_parse_listen) ||
6603 !cfg_register_section("frontend", cfg_parse_listen) ||
6604 !cfg_register_section("backend", cfg_parse_listen) ||
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006605 !cfg_register_section("defaults", cfg_parse_listen) ||
6606 !cfg_register_section("global", cfg_parse_global) ||
6607 !cfg_register_section("userlist", cfg_parse_users) ||
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006608 !cfg_register_section("peers", cfg_parse_peers) ||
Simon Horman0d16a402015-01-30 11:22:58 +09006609 !cfg_register_section("mailers", cfg_parse_mailers) ||
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006610 !cfg_register_section("namespace_list", cfg_parse_netns))
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006611 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006612
Willy Tarreaubaaee002006-06-26 02:48:02 +02006613 if ((f=fopen(file,"r")) == NULL)
6614 return -1;
6615
William Lallemandb2f07452015-05-12 14:27:13 +02006616next_line:
William Lallemand64e84512015-05-12 14:25:37 +02006617 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02006618 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006619 char *end;
6620 char *args[MAX_LINE_ARGS + 1];
6621 char *line = thisline;
William Lallemandf9873ba2015-05-05 17:37:14 +02006622 int dquote = 0; /* double quote */
6623 int squote = 0; /* simple quote */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006624
Willy Tarreaubaaee002006-06-26 02:48:02 +02006625 linenum++;
6626
6627 end = line + strlen(line);
6628
William Lallemand64e84512015-05-12 14:25:37 +02006629 if (end-line == linesize-1 && *(end-1) != '\n') {
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006630 /* Check if we reached the limit and the last char is not \n.
6631 * Watch out for the last line without the terminating '\n'!
6632 */
William Lallemand64e84512015-05-12 14:25:37 +02006633 char *newline;
6634 int newlinesize = linesize * 2;
6635
6636 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
6637 if (newline == NULL) {
6638 Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
6639 file, linenum);
6640 err_code |= ERR_ALERT | ERR_FATAL;
6641 continue;
6642 }
6643
6644 readbytes = linesize - 1;
6645 linesize = newlinesize;
6646 thisline = newline;
6647 continue;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006648 }
6649
William Lallemand64e84512015-05-12 14:25:37 +02006650 readbytes = 0;
6651
Willy Tarreaubaaee002006-06-26 02:48:02 +02006652 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006653 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006654 line++;
William Lallemandf9873ba2015-05-05 17:37:14 +02006655
Willy Tarreaubaaee002006-06-26 02:48:02 +02006656 arg = 0;
6657 args[arg] = line;
6658
6659 while (*line && arg < MAX_LINE_ARGS) {
William Lallemandf9873ba2015-05-05 17:37:14 +02006660 if (*line == '"' && !squote) { /* double quote outside single quotes */
6661 if (dquote)
6662 dquote = 0;
6663 else
6664 dquote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02006665 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02006666 end--;
6667 }
6668 else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
6669 if (squote)
6670 squote = 0;
6671 else
6672 squote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02006673 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02006674 end--;
6675 }
6676 else if (*line == '\\' && !squote) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006677 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
6678 * C equivalent value. Other combinations left unchanged (eg: \1).
6679 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006680 int skip = 0;
6681 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
6682 *line = line[1];
6683 skip = 1;
6684 }
6685 else if (line[1] == 'r') {
6686 *line = '\r';
6687 skip = 1;
William Lallemandf9873ba2015-05-05 17:37:14 +02006688 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006689 else if (line[1] == 'n') {
6690 *line = '\n';
6691 skip = 1;
6692 }
6693 else if (line[1] == 't') {
6694 *line = '\t';
6695 skip = 1;
6696 }
6697 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01006698 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006699 unsigned char hex1, hex2;
6700 hex1 = toupper(line[2]) - '0';
6701 hex2 = toupper(line[3]) - '0';
6702 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
6703 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
6704 *line = (hex1<<4) + hex2;
6705 skip = 3;
6706 }
6707 else {
6708 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006709 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006710 }
William Lallemandf9873ba2015-05-05 17:37:14 +02006711 } else if (line[1] == '"') {
6712 *line = '"';
6713 skip = 1;
6714 } else if (line[1] == '\'') {
6715 *line = '\'';
6716 skip = 1;
William Lallemandb2f07452015-05-12 14:27:13 +02006717 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
6718 *line = '$';
6719 skip = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006720 }
6721 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01006722 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006723 end -= skip;
6724 }
6725 line++;
6726 }
William Lallemandf9873ba2015-05-05 17:37:14 +02006727 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006728 /* end of string, end of loop */
6729 *line = 0;
6730 break;
6731 }
William Lallemandf9873ba2015-05-05 17:37:14 +02006732 else if (!squote && !dquote && isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006733 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006734 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006735 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006736 line++;
6737 args[++arg] = line;
6738 }
William Lallemandb2f07452015-05-12 14:27:13 +02006739 else if (dquote && *line == '$') {
6740 /* environment variables are evaluated inside double quotes */
6741 char *var_beg;
6742 char *var_end;
6743 char save_char;
6744 char *value;
6745 int val_len;
6746 int newlinesize;
6747 int braces = 0;
6748
6749 var_beg = line + 1;
6750 var_end = var_beg;
6751
6752 if (*var_beg == '{') {
6753 var_beg++;
6754 var_end++;
6755 braces = 1;
6756 }
6757
6758 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
6759 Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
6760 err_code |= ERR_ALERT | ERR_FATAL;
6761 goto next_line; /* skip current line */
6762 }
6763
6764 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
6765 var_end++;
6766
6767 save_char = *var_end;
6768 *var_end = '\0';
6769 value = getenv(var_beg);
6770 *var_end = save_char;
6771 val_len = value ? strlen(value) : 0;
6772
6773 if (braces) {
6774 if (*var_end == '}') {
6775 var_end++;
6776 braces = 0;
6777 } else {
6778 Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
6779 err_code |= ERR_ALERT | ERR_FATAL;
6780 goto next_line; /* skip current line */
6781 }
6782 }
6783
6784 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
6785
6786 /* if not enough space in thisline */
6787 if (newlinesize > linesize) {
6788 char *newline;
6789
6790 newline = realloc(thisline, newlinesize * sizeof(*thisline));
6791 if (newline == NULL) {
6792 Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
6793 err_code |= ERR_ALERT | ERR_FATAL;
6794 goto next_line; /* slip current line */
6795 }
6796 /* recompute pointers if realloc returns a new pointer */
6797 if (newline != thisline) {
6798 int i;
6799 int diff;
6800
6801 for (i = 0; i <= arg; i++) {
6802 diff = args[i] - thisline;
6803 args[i] = newline + diff;
6804 }
6805
6806 diff = var_end - thisline;
6807 var_end = newline + diff;
6808 diff = end - thisline;
6809 end = newline + diff;
6810 diff = line - thisline;
6811 line = newline + diff;
6812 thisline = newline;
6813 }
6814 linesize = newlinesize;
6815 }
6816
6817 /* insert value inside the line */
6818 memmove(line + val_len, var_end, end - var_end + 1);
6819 memcpy(line, value, val_len);
6820 end += val_len - (var_end - line);
6821 line += val_len;
6822 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006823 else {
6824 line++;
6825 }
6826 }
William Lallemandb2f07452015-05-12 14:27:13 +02006827
William Lallemandf9873ba2015-05-05 17:37:14 +02006828 if (dquote) {
6829 Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
6830 err_code |= ERR_ALERT | ERR_FATAL;
6831 }
6832
6833 if (squote) {
6834 Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
6835 err_code |= ERR_ALERT | ERR_FATAL;
6836 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006837
6838 /* empty line */
6839 if (!**args)
6840 continue;
6841
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006842 if (*line) {
6843 /* we had to stop due to too many args.
6844 * Let's terminate the string, print the offending part then cut the
6845 * last arg.
6846 */
6847 while (*line && *line != '#' && *line != '\n' && *line != '\r')
6848 line++;
6849 *line = '\0';
6850
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01006851 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01006852 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006853 err_code |= ERR_ALERT | ERR_FATAL;
6854 args[arg] = line;
6855 }
6856
Willy Tarreau540abe42007-05-02 20:50:16 +02006857 /* zero out remaining args and ensure that at least one entry
6858 * is zeroed out.
6859 */
6860 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006861 args[arg] = line;
6862 }
6863
Willy Tarreau3842f002009-06-14 11:39:52 +02006864 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006865 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006866 char *tmp;
6867
Willy Tarreau3842f002009-06-14 11:39:52 +02006868 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02006869 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006870 for (arg=0; *args[arg+1]; arg++)
6871 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02006872 *tmp = '\0'; // fix the next arg to \0
6873 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006874 }
Willy Tarreau3842f002009-06-14 11:39:52 +02006875 else if (!strcmp(args[0], "default")) {
6876 kwm = KWM_DEF;
6877 for (arg=0; *args[arg+1]; arg++)
6878 args[arg] = args[arg+1]; // shift args after inversion
6879 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006880
William Lallemand0f99e342011-10-12 17:50:54 +02006881 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
6882 strcmp(args[0], "log") != 0) {
6883 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02006884 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006885 }
6886
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006887 /* detect section start */
6888 list_for_each_entry(ics, &sections, list) {
6889 if (strcmp(args[0], ics->section_name) == 0) {
6890 cursection = ics->section_name;
6891 cs = ics;
6892 break;
6893 }
Emeric Brun32da3c42010-09-23 18:39:19 +02006894 }
6895
Willy Tarreaubaaee002006-06-26 02:48:02 +02006896 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006897 if (cs)
6898 err_code |= cs->section_parser(file, linenum, args, kwm);
6899 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006900 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006901 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006902 }
Willy Tarreau058e9072009-07-20 09:30:05 +02006903
6904 if (err_code & ERR_ABORT)
6905 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006906 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01006907 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02006908 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006909 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02006910 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006911}
6912
Willy Tarreau64ab6072014-09-16 12:17:36 +02006913/* This function propagates processes from frontend <from> to backend <to> so
6914 * that it is always guaranteed that a backend pointed to by a frontend is
6915 * bound to all of its processes. After that, if the target is a "listen"
6916 * instance, the function recursively descends the target's own targets along
Willy Tarreau98d04852015-05-26 12:18:29 +02006917 * default_backend and use_backend rules. Since the bits are
Willy Tarreau64ab6072014-09-16 12:17:36 +02006918 * checked first to ensure that <to> is already bound to all processes of
6919 * <from>, there is no risk of looping and we ensure to follow the shortest
6920 * path to the destination.
6921 *
6922 * It is possible to set <to> to NULL for the first call so that the function
6923 * takes care of visiting the initial frontend in <from>.
6924 *
6925 * It is important to note that the function relies on the fact that all names
6926 * have already been resolved.
6927 */
6928void propagate_processes(struct proxy *from, struct proxy *to)
6929{
6930 struct switching_rule *rule;
Willy Tarreau64ab6072014-09-16 12:17:36 +02006931
6932 if (to) {
6933 /* check whether we need to go down */
6934 if (from->bind_proc &&
6935 (from->bind_proc & to->bind_proc) == from->bind_proc)
6936 return;
6937
6938 if (!from->bind_proc && !to->bind_proc)
6939 return;
6940
6941 to->bind_proc = from->bind_proc ?
6942 (to->bind_proc | from->bind_proc) : 0;
6943
6944 /* now propagate down */
6945 from = to;
6946 }
6947
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01006948 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02006949 return;
6950
Willy Tarreauf6b70012014-12-18 14:00:43 +01006951 if (from->state == PR_STSTOPPED)
6952 return;
6953
Willy Tarreau64ab6072014-09-16 12:17:36 +02006954 /* default_backend */
6955 if (from->defbe.be)
6956 propagate_processes(from, from->defbe.be);
6957
6958 /* use_backend */
6959 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02006960 if (rule->dynamic)
6961 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02006962 to = rule->be.backend;
6963 propagate_processes(from, to);
6964 }
Willy Tarreau64ab6072014-09-16 12:17:36 +02006965}
6966
Willy Tarreaubb925012009-07-23 13:36:36 +02006967/*
6968 * Returns the error code, 0 if OK, or any combination of :
6969 * - ERR_ABORT: must abort ASAP
6970 * - ERR_FATAL: we can continue parsing but not start the service
6971 * - ERR_WARN: a warning has been emitted
6972 * - ERR_ALERT: an alert has been emitted
6973 * Only the two first ones can stop processing, the two others are just
6974 * indicators.
6975 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006976int check_config_validity()
6977{
6978 int cfgerr = 0;
6979 struct proxy *curproxy = NULL;
6980 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02006981 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006982 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006983 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006984
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006985 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006986 /*
6987 * Now, check for the integrity of all that we have collected.
6988 */
6989
6990 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02006991 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006992
Willy Tarreau193b8c62012-11-22 00:17:38 +01006993 if (!global.tune.max_http_hdr)
6994 global.tune.max_http_hdr = MAX_HTTP_HDR;
6995
6996 if (!global.tune.cookie_len)
6997 global.tune.cookie_len = CAPTURE_LEN;
6998
6999 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
7000
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007001 /* Post initialisation of the users and groups lists. */
7002 err_code = userlist_postinit();
7003 if (err_code != ERR_NONE)
7004 goto out;
7005
Willy Tarreau55bc0f82009-03-15 14:51:53 +01007006 /* first, we will invert the proxy list order */
7007 curproxy = NULL;
7008 while (proxy) {
7009 struct proxy *next;
7010
7011 next = proxy->next;
7012 proxy->next = curproxy;
7013 curproxy = proxy;
7014 if (!next)
7015 break;
7016 proxy = next;
7017 }
7018
Willy Tarreau419ead82014-09-16 13:41:21 +02007019 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007020 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007021 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01007022 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007023 struct tcp_rule *trule;
Willy Tarreau09448f72014-06-25 18:12:15 +02007024 struct http_req_rule *hrqrule;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007025 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01007026 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007027
Willy Tarreau050536d2012-10-04 08:47:34 +02007028 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007029 /* proxy ID not set, use automatic numbering with first
7030 * spare entry starting with next_pxid.
7031 */
7032 next_pxid = get_next_id(&used_proxy_id, next_pxid);
7033 curproxy->conf.id.key = curproxy->uuid = next_pxid;
7034 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007035 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007036 next_pxid++;
7037
Willy Tarreau55ea7572007-06-17 19:56:27 +02007038
Willy Tarreaubaaee002006-06-26 02:48:02 +02007039 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02007040 /* ensure we don't keep listeners uselessly bound */
7041 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02007042 free((void *)curproxy->table.peers.name);
7043 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007044 continue;
7045 }
7046
Willy Tarreau102df612014-05-07 23:56:38 +02007047 /* Check multi-process mode compatibility for the current proxy */
7048
7049 if (curproxy->bind_proc) {
7050 /* an explicit bind-process was specified, let's check how many
7051 * processes remain.
7052 */
7053 nbproc = popcount(curproxy->bind_proc);
7054
7055 curproxy->bind_proc &= nbits(global.nbproc);
7056 if (!curproxy->bind_proc && nbproc == 1) {
7057 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);
7058 curproxy->bind_proc = 1;
7059 }
7060 else if (!curproxy->bind_proc && nbproc > 1) {
7061 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);
7062 curproxy->bind_proc = 0;
7063 }
7064 }
7065
Willy Tarreau3d209582014-05-09 17:06:11 +02007066 /* check and reduce the bind-proc of each listener */
7067 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7068 unsigned long mask;
7069
7070 if (!bind_conf->bind_proc)
7071 continue;
7072
7073 mask = nbits(global.nbproc);
7074 if (curproxy->bind_proc)
7075 mask &= curproxy->bind_proc;
7076 /* mask cannot be null here thanks to the previous checks */
7077
7078 nbproc = popcount(bind_conf->bind_proc);
7079 bind_conf->bind_proc &= mask;
7080
7081 if (!bind_conf->bind_proc && nbproc == 1) {
7082 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",
7083 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7084 bind_conf->bind_proc = mask & ~(mask - 1);
7085 }
7086 else if (!bind_conf->bind_proc && nbproc > 1) {
7087 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",
7088 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7089 bind_conf->bind_proc = 0;
7090 }
7091 }
7092
Willy Tarreauff01a212009-03-15 13:46:16 +01007093 switch (curproxy->mode) {
7094 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007095 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007096 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007097 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
7098 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007099 cfgerr++;
7100 }
7101
7102 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007103 Warning("config : servers will be ignored for %s '%s'.\n",
7104 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007105 break;
7106
7107 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007108 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007109 break;
7110
7111 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01007112 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01007113 break;
7114 }
7115
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007116 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007117 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007118 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007119 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
7120 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007121 cfgerr++;
7122 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007123#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007124 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007125 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
7126 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007127 cfgerr++;
7128 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007129#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02007130 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007131 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
7132 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007133 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007134 }
7135 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02007136 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007137 /* If no LB algo is set in a backend, and we're not in
7138 * transparent mode, dispatch mode nor proxy mode, we
7139 * want to use balance roundrobin by default.
7140 */
7141 curproxy->lbprm.algo &= ~BE_LB_ALGO;
7142 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007143 }
7144 }
Willy Tarreau193cf932007-09-17 10:17:23 +02007145
Willy Tarreau1620ec32011-08-06 17:05:02 +02007146 if (curproxy->options & PR_O_DISPATCH)
7147 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
7148 else if (curproxy->options & PR_O_HTTP_PROXY)
7149 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
7150 else if (curproxy->options & PR_O_TRANSP)
7151 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01007152
Willy Tarreau1620ec32011-08-06 17:05:02 +02007153 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
7154 if (curproxy->options & PR_O_DISABLE404) {
7155 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7156 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
7157 err_code |= ERR_WARN;
7158 curproxy->options &= ~PR_O_DISABLE404;
7159 }
7160 if (curproxy->options2 & PR_O2_CHK_SNDST) {
7161 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7162 "send-state", proxy_type_str(curproxy), curproxy->id);
7163 err_code |= ERR_WARN;
7164 curproxy->options &= ~PR_O2_CHK_SNDST;
7165 }
Willy Tarreauef781042010-01-27 11:53:01 +01007166 }
7167
Simon Horman98637e52014-06-20 12:30:16 +09007168 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
7169 if (!global.external_check) {
7170 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
7171 curproxy->id, "option external-check");
7172 cfgerr++;
7173 }
7174 if (!curproxy->check_command) {
7175 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
7176 curproxy->id, "option external-check");
7177 cfgerr++;
7178 }
7179 }
7180
Simon Horman64e34162015-02-06 11:11:57 +09007181 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007182 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
7183 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Simon Horman64e34162015-02-06 11:11:57 +09007184 "'email-alert from', 'email-alert level' 'email-alert mailer', "
7185 "'email-alert hostname', or 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007186 "requrires each of 'email-alert from', 'email-alert mailer' and 'email-alert' "
7187 "to be present).\n",
7188 proxy_type_str(curproxy), curproxy->id);
7189 err_code |= ERR_WARN;
7190 free_email_alert(curproxy);
7191 }
7192 if (!curproxy->email_alert.myhostname)
7193 curproxy->email_alert.myhostname = hostname;
Simon Horman9dc49962015-01-30 11:22:59 +09007194 }
7195
Simon Horman98637e52014-06-20 12:30:16 +09007196 if (curproxy->check_command) {
7197 int clear = 0;
7198 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7199 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7200 "external-check command", proxy_type_str(curproxy), curproxy->id);
7201 err_code |= ERR_WARN;
7202 clear = 1;
7203 }
7204 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
7205 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-command path' is not set.\n",
7206 curproxy->id, "external-check command");
7207 cfgerr++;
7208 }
7209 if (clear) {
7210 free(curproxy->check_command);
7211 curproxy->check_command = NULL;
7212 }
7213 }
7214
7215 if (curproxy->check_path) {
7216 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7217 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7218 "external-check path", proxy_type_str(curproxy), curproxy->id);
7219 err_code |= ERR_WARN;
7220 free(curproxy->check_path);
7221 curproxy->check_path = NULL;
7222 }
7223 }
7224
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007225 /* if a default backend was specified, let's find it */
7226 if (curproxy->defbe.name) {
7227 struct proxy *target;
7228
Willy Tarreauafb39922015-05-26 12:04:09 +02007229 target = proxy_be_by_name(curproxy->defbe.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007230 if (!target) {
7231 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
7232 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007233 cfgerr++;
7234 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007235 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
7236 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02007237 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007238 } else if (target->mode != curproxy->mode &&
7239 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7240
7241 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) as its default backend (see 'mode').\n",
7242 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7243 curproxy->conf.file, curproxy->conf.line,
7244 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7245 target->conf.file, target->conf.line);
7246 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007247 } else {
7248 free(curproxy->defbe.name);
7249 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01007250
7251 /* Emit a warning if this proxy also has some servers */
7252 if (curproxy->srv) {
7253 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
7254 curproxy->id);
7255 err_code |= ERR_WARN;
7256 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007257 }
7258 }
7259
Willy Tarreau55ea7572007-06-17 19:56:27 +02007260 /* find the target proxy for 'use_backend' rules */
7261 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007262 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007263 struct logformat_node *node;
7264 char *pxname;
7265
7266 /* Try to parse the string as a log format expression. If the result
7267 * of the parsing is only one entry containing a simple string, then
7268 * it's a standard string corresponding to a static rule, thus the
7269 * parsing is cancelled and be.name is restored to be resolved.
7270 */
7271 pxname = rule->be.name;
7272 LIST_INIT(&rule->be.expr);
7273 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
7274 curproxy->conf.args.file, curproxy->conf.args.line);
7275 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
7276
7277 if (!LIST_ISEMPTY(&rule->be.expr)) {
7278 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
7279 rule->dynamic = 1;
7280 free(pxname);
7281 continue;
7282 }
7283 /* simple string: free the expression and fall back to static rule */
7284 free(node->arg);
7285 free(node);
7286 }
7287
7288 rule->dynamic = 0;
7289 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007290
Willy Tarreauafb39922015-05-26 12:04:09 +02007291 target = proxy_be_by_name(rule->be.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007292 if (!target) {
7293 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
7294 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007295 cfgerr++;
7296 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007297 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
7298 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007299 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007300 } else if (target->mode != curproxy->mode &&
7301 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7302
7303 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) in a 'use_backend' rule (see 'mode').\n",
7304 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7305 curproxy->conf.file, curproxy->conf.line,
7306 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7307 target->conf.file, target->conf.line);
7308 cfgerr++;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007309 } else {
7310 free((void *)rule->be.name);
7311 rule->be.backend = target;
7312 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007313 }
7314
Willy Tarreau64ab6072014-09-16 12:17:36 +02007315 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007316 list_for_each_entry(srule, &curproxy->server_rules, list) {
7317 struct server *target = findserver(curproxy, srule->srv.name);
7318
7319 if (!target) {
7320 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7321 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7322 cfgerr++;
7323 continue;
7324 }
7325 free((void *)srule->srv.name);
7326 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007327 }
7328
Emeric Brunb982a3d2010-01-04 15:45:53 +01007329 /* find the target table for 'stick' rules */
7330 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7331 struct proxy *target;
7332
Emeric Brun1d33b292010-01-04 15:47:17 +01007333 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7334 if (mrule->flags & STK_IS_STORE)
7335 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7336
Emeric Brunb982a3d2010-01-04 15:45:53 +01007337 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007338 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007339 else
7340 target = curproxy;
7341
7342 if (!target) {
7343 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7344 curproxy->id, mrule->table.name);
7345 cfgerr++;
7346 }
7347 else if (target->table.size == 0) {
7348 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7349 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7350 cfgerr++;
7351 }
Willy Tarreau12785782012-04-27 21:37:17 +02007352 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7353 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007354 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7355 cfgerr++;
7356 }
7357 else {
7358 free((void *)mrule->table.name);
7359 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007360 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007361 }
7362 }
7363
7364 /* find the target table for 'store response' rules */
7365 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7366 struct proxy *target;
7367
Emeric Brun1d33b292010-01-04 15:47:17 +01007368 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7369
Emeric Brunb982a3d2010-01-04 15:45:53 +01007370 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007371 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007372 else
7373 target = curproxy;
7374
7375 if (!target) {
7376 Alert("Proxy '%s': unable to find store table '%s'.\n",
7377 curproxy->id, mrule->table.name);
7378 cfgerr++;
7379 }
7380 else if (target->table.size == 0) {
7381 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7382 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7383 cfgerr++;
7384 }
Willy Tarreau12785782012-04-27 21:37:17 +02007385 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7386 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007387 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7388 cfgerr++;
7389 }
7390 else {
7391 free((void *)mrule->table.name);
7392 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007393 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007394 }
7395 }
7396
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007397 /* find the target table for 'tcp-request' layer 4 rules */
7398 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
7399 struct proxy *target;
7400
Willy Tarreaub4c84932013-07-23 19:15:30 +02007401 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007402 continue;
7403
7404 if (trule->act_prm.trk_ctr.table.n)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007405 target = proxy_tbl_by_name(trule->act_prm.trk_ctr.table.n);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007406 else
7407 target = curproxy;
7408
7409 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007410 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7411 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007412 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007413 cfgerr++;
7414 }
7415 else if (target->table.size == 0) {
7416 Alert("Proxy '%s': table '%s' used but not configured.\n",
7417 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
7418 cfgerr++;
7419 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01007420 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
7421 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7422 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007423 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007424 cfgerr++;
7425 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007426 else {
7427 free(trule->act_prm.trk_ctr.table.n);
7428 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007429 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007430 * to pass a list of counters to track and allocate them right here using
7431 * stktable_alloc_data_type().
7432 */
7433 }
7434 }
7435
Willy Tarreaud1f96522010-08-03 19:34:32 +02007436 /* find the target table for 'tcp-request' layer 6 rules */
7437 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7438 struct proxy *target;
7439
Willy Tarreaub4c84932013-07-23 19:15:30 +02007440 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02007441 continue;
7442
7443 if (trule->act_prm.trk_ctr.table.n)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007444 target = proxy_tbl_by_name(trule->act_prm.trk_ctr.table.n);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007445 else
7446 target = curproxy;
7447
7448 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007449 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7450 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007451 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02007452 cfgerr++;
7453 }
7454 else if (target->table.size == 0) {
7455 Alert("Proxy '%s': table '%s' used but not configured.\n",
7456 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
7457 cfgerr++;
7458 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01007459 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
7460 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7461 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007462 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007463 cfgerr++;
7464 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02007465 else {
7466 free(trule->act_prm.trk_ctr.table.n);
7467 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007468 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02007469 * to pass a list of counters to track and allocate them right here using
7470 * stktable_alloc_data_type().
7471 */
7472 }
7473 }
7474
Willy Tarreau09448f72014-06-25 18:12:15 +02007475 /* find the target table for 'http-request' layer 7 rules */
7476 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7477 struct proxy *target;
7478
7479 if (hrqrule->action < HTTP_REQ_ACT_TRK_SC0 || hrqrule->action > HTTP_REQ_ACT_TRK_SCMAX)
7480 continue;
7481
7482 if (hrqrule->act_prm.trk_ctr.table.n)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007483 target = proxy_tbl_by_name(hrqrule->act_prm.trk_ctr.table.n);
Willy Tarreau09448f72014-06-25 18:12:15 +02007484 else
7485 target = curproxy;
7486
7487 if (!target) {
7488 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7489 curproxy->id, hrqrule->act_prm.trk_ctr.table.n,
7490 http_req_trk_idx(hrqrule->action));
7491 cfgerr++;
7492 }
7493 else if (target->table.size == 0) {
7494 Alert("Proxy '%s': table '%s' used but not configured.\n",
7495 curproxy->id, hrqrule->act_prm.trk_ctr.table.n ? hrqrule->act_prm.trk_ctr.table.n : curproxy->id);
7496 cfgerr++;
7497 }
7498 else if (!stktable_compatible_sample(hrqrule->act_prm.trk_ctr.expr, target->table.type)) {
7499 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7500 curproxy->id, hrqrule->act_prm.trk_ctr.table.n ? hrqrule->act_prm.trk_ctr.table.n : curproxy->id,
7501 http_req_trk_idx(hrqrule->action));
7502 cfgerr++;
7503 }
7504 else {
7505 free(hrqrule->act_prm.trk_ctr.table.n);
7506 hrqrule->act_prm.trk_ctr.table.t = &target->table;
7507 /* Note: if we decide to enhance the track-sc syntax, we may be able
7508 * to pass a list of counters to track and allocate them right here using
7509 * stktable_alloc_data_type().
7510 */
7511 }
7512 }
7513
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02007514 /* move any "block" rules at the beginning of the http-request rules */
7515 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
7516 /* insert block_rules into http_req_rules at the beginning */
7517 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
7518 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
7519 curproxy->block_rules.n->p = &curproxy->http_req_rules;
7520 curproxy->http_req_rules.n = curproxy->block_rules.n;
7521 LIST_INIT(&curproxy->block_rules);
7522 }
7523
Emeric Brun32da3c42010-09-23 18:39:19 +02007524 if (curproxy->table.peers.name) {
7525 struct peers *curpeers = peers;
7526
7527 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
7528 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
7529 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01007530 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02007531 break;
7532 }
7533 }
7534
7535 if (!curpeers) {
7536 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
7537 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007538 free((void *)curproxy->table.peers.name);
7539 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007540 cfgerr++;
7541 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02007542 else if (curpeers->state == PR_STSTOPPED) {
7543 /* silently disable this peers section */
7544 curproxy->table.peers.p = NULL;
7545 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007546 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02007547 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
7548 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007549 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007550 cfgerr++;
7551 }
7552 }
7553
Simon Horman9dc49962015-01-30 11:22:59 +09007554
7555 if (curproxy->email_alert.mailers.name) {
7556 struct mailers *curmailers = mailers;
7557
7558 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
7559 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
7560 free(curproxy->email_alert.mailers.name);
7561 curproxy->email_alert.mailers.m = curmailers;
7562 curmailers->users++;
7563 break;
7564 }
7565 }
7566
7567 if (!curmailers) {
7568 Alert("Proxy '%s': unable to find mailers '%s'.\n",
7569 curproxy->id, curproxy->email_alert.mailers.name);
7570 free_email_alert(curproxy);
7571 cfgerr++;
7572 }
7573 }
7574
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007575 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01007576 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007577 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
7578 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
7579 "proxy", curproxy->id);
7580 cfgerr++;
7581 goto out_uri_auth_compat;
7582 }
7583
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007584 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007585 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01007586 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01007587 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007588
Willy Tarreau95fa4692010-02-01 13:05:50 +01007589 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
7590 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007591
7592 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007593 uri_auth_compat_req[i++] = "realm";
7594 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
7595 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007596
Willy Tarreau95fa4692010-02-01 13:05:50 +01007597 uri_auth_compat_req[i++] = "unless";
7598 uri_auth_compat_req[i++] = "{";
7599 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
7600 uri_auth_compat_req[i++] = "}";
7601 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007602
Willy Tarreauff011f22011-01-06 17:51:27 +01007603 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
7604 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007605 cfgerr++;
7606 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007607 }
7608
Willy Tarreauff011f22011-01-06 17:51:27 +01007609 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01007610
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007611 if (curproxy->uri_auth->auth_realm) {
7612 free(curproxy->uri_auth->auth_realm);
7613 curproxy->uri_auth->auth_realm = NULL;
7614 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007615
7616 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007617 }
7618out_uri_auth_compat:
7619
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007620 /* compile the log format */
7621 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02007622 if (curproxy->conf.logformat_string != default_http_log_format &&
7623 curproxy->conf.logformat_string != default_tcp_log_format &&
7624 curproxy->conf.logformat_string != clf_http_log_format)
7625 free(curproxy->conf.logformat_string);
7626 curproxy->conf.logformat_string = NULL;
7627 free(curproxy->conf.lfs_file);
7628 curproxy->conf.lfs_file = NULL;
7629 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007630 }
7631
Willy Tarreau62a61232013-04-12 18:13:46 +02007632 if (curproxy->conf.logformat_string) {
7633 curproxy->conf.args.ctx = ARGC_LOG;
7634 curproxy->conf.args.file = curproxy->conf.lfs_file;
7635 curproxy->conf.args.line = curproxy->conf.lfs_line;
7636 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007637 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007638 curproxy->conf.args.file = NULL;
7639 curproxy->conf.args.line = 0;
7640 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007641
Willy Tarreau62a61232013-04-12 18:13:46 +02007642 if (curproxy->conf.uniqueid_format_string) {
7643 curproxy->conf.args.ctx = ARGC_UIF;
7644 curproxy->conf.args.file = curproxy->conf.uif_file;
7645 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01007646 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Godbachd9722032014-12-18 15:44:58 +08007647 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007648 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007649 curproxy->conf.args.file = NULL;
7650 curproxy->conf.args.line = 0;
7651 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007652
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007653 /* only now we can check if some args remain unresolved.
7654 * This must be done after the users and groups resolution.
7655 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007656 cfgerr += smp_resolve_args(curproxy);
7657 if (!cfgerr)
7658 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01007659
Willy Tarreau2738a142006-07-08 17:28:09 +02007660 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007661 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02007662 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02007663 (!curproxy->timeout.connect ||
7664 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007665 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02007666 " | While not properly invalid, you will certainly encounter various problems\n"
7667 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01007668 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007669 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007670 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02007671 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02007672
Willy Tarreau1fa31262007-12-03 00:36:16 +01007673 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
7674 * We must still support older configurations, so let's find out whether those
7675 * parameters have been set or must be copied from contimeouts.
7676 */
7677 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007678 if (!curproxy->timeout.tarpit ||
7679 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007680 /* tarpit timeout not set. We search in the following order:
7681 * default.tarpit, curr.connect, default.connect.
7682 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007683 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007684 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007685 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007686 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007687 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007688 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007689 }
7690 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007691 (!curproxy->timeout.queue ||
7692 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007693 /* queue timeout not set. We search in the following order:
7694 * default.queue, curr.connect, default.connect.
7695 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007696 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007697 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007698 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007699 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007700 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007701 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007702 }
7703 }
7704
Willy Tarreau1620ec32011-08-06 17:05:02 +02007705 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01007706 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
7707 curproxy->check_req = (char *)malloc(curproxy->check_len);
7708 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02007709 }
7710
Willy Tarreau215663d2014-06-13 18:30:23 +02007711 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
7712 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
7713 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
7714 proxy_type_str(curproxy), curproxy->id);
7715 err_code |= ERR_WARN;
7716 }
7717
Willy Tarreau193b8c62012-11-22 00:17:38 +01007718 /* ensure that cookie capture length is not too large */
7719 if (curproxy->capture_len >= global.tune.cookie_len) {
7720 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
7721 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
7722 err_code |= ERR_WARN;
7723 curproxy->capture_len = global.tune.cookie_len - 1;
7724 }
7725
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007726 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01007727 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02007728 curproxy->req_cap_pool = create_pool("ptrcap",
7729 curproxy->nb_req_cap * sizeof(char *),
7730 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01007731 }
7732
7733 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02007734 curproxy->rsp_cap_pool = create_pool("ptrcap",
7735 curproxy->nb_rsp_cap * sizeof(char *),
7736 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01007737 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007738
Willy Tarreaubaaee002006-06-26 02:48:02 +02007739 /* first, we will invert the servers list order */
7740 newsrv = NULL;
7741 while (curproxy->srv) {
7742 struct server *next;
7743
7744 next = curproxy->srv->next;
7745 curproxy->srv->next = newsrv;
7746 newsrv = curproxy->srv;
7747 if (!next)
7748 break;
7749 curproxy->srv = next;
7750 }
7751
Willy Tarreau17edc812014-01-03 12:14:34 +01007752 /* Check that no server name conflicts. This causes trouble in the stats.
7753 * We only emit a warning for the first conflict affecting each server,
7754 * in order to avoid combinatory explosion if all servers have the same
7755 * name. We do that only for servers which do not have an explicit ID,
7756 * because these IDs were made also for distinguishing them and we don't
7757 * want to annoy people who correctly manage them.
7758 */
7759 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
7760 struct server *other_srv;
7761
7762 if (newsrv->puid)
7763 continue;
7764
7765 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
7766 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
7767 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
7768 newsrv->conf.file, newsrv->conf.line,
7769 proxy_type_str(curproxy), curproxy->id,
7770 newsrv->id, other_srv->conf.line);
7771 break;
7772 }
7773 }
7774 }
7775
Willy Tarreaudd701652010-05-25 23:03:02 +02007776 /* assign automatic UIDs to servers which don't have one yet */
7777 next_id = 1;
7778 newsrv = curproxy->srv;
7779 while (newsrv != NULL) {
7780 if (!newsrv->puid) {
7781 /* server ID not set, use automatic numbering with first
7782 * spare entry starting with next_svid.
7783 */
7784 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
7785 newsrv->conf.id.key = newsrv->puid = next_id;
7786 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
7787 }
7788 next_id++;
7789 newsrv = newsrv->next;
7790 }
7791
Willy Tarreau20697042007-11-15 23:26:18 +01007792 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01007793 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007794
Willy Tarreau62c3be22012-01-20 13:12:32 +01007795 /*
7796 * If this server supports a maxconn parameter, it needs a dedicated
7797 * tasks to fill the emptied slots when a connection leaves.
7798 * Also, resolve deferred tracking dependency if needed.
7799 */
7800 newsrv = curproxy->srv;
7801 while (newsrv != NULL) {
7802 if (newsrv->minconn > newsrv->maxconn) {
7803 /* Only 'minconn' was specified, or it was higher than or equal
7804 * to 'maxconn'. Let's turn this into maxconn and clean it, as
7805 * this will avoid further useless expensive computations.
7806 */
7807 newsrv->maxconn = newsrv->minconn;
7808 } else if (newsrv->maxconn && !newsrv->minconn) {
7809 /* minconn was not specified, so we set it to maxconn */
7810 newsrv->minconn = newsrv->maxconn;
7811 }
7812
Emeric Brun01f8e2f2012-05-18 16:02:00 +02007813#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02007814 if (newsrv->use_ssl || newsrv->check.use_ssl)
7815 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02007816#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02007817
Willy Tarreau2f075e92013-12-03 11:11:34 +01007818 /* set the check type on the server */
7819 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
7820
Willy Tarreau62c3be22012-01-20 13:12:32 +01007821 if (newsrv->trackit) {
7822 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02007823 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007824 char *pname, *sname;
7825
7826 pname = newsrv->trackit;
7827 sname = strrchr(pname, '/');
7828
7829 if (sname)
7830 *sname++ = '\0';
7831 else {
7832 sname = pname;
7833 pname = NULL;
7834 }
7835
7836 if (pname) {
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007837 px = proxy_be_by_name(pname);
Willy Tarreau62c3be22012-01-20 13:12:32 +01007838 if (!px) {
7839 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
7840 proxy_type_str(curproxy), curproxy->id,
7841 newsrv->id, pname);
7842 cfgerr++;
7843 goto next_srv;
7844 }
7845 } else
7846 px = curproxy;
7847
7848 srv = findserver(px, sname);
7849 if (!srv) {
7850 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
7851 proxy_type_str(curproxy), curproxy->id,
7852 newsrv->id, sname);
7853 cfgerr++;
7854 goto next_srv;
7855 }
7856
Willy Tarreau32091232014-05-16 13:52:00 +02007857 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
7858 !(srv->agent.state & CHK_ST_CONFIGURED) &&
7859 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01007860 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02007861 "tracking as it does not have any check nor agent enabled.\n",
7862 proxy_type_str(curproxy), curproxy->id,
7863 newsrv->id, px->id, srv->id);
7864 cfgerr++;
7865 goto next_srv;
7866 }
7867
7868 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
7869
7870 if (loop) {
7871 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
7872 "belongs to a tracking chain looping back to %s/%s.\n",
7873 proxy_type_str(curproxy), curproxy->id,
7874 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01007875 cfgerr++;
7876 goto next_srv;
7877 }
7878
7879 if (curproxy != px &&
7880 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
7881 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
7882 "tracking: disable-on-404 option inconsistency.\n",
7883 proxy_type_str(curproxy), curproxy->id,
7884 newsrv->id, px->id, srv->id);
7885 cfgerr++;
7886 goto next_srv;
7887 }
7888
7889 /* if the other server is forced disabled, we have to do the same here */
Willy Tarreau20125212014-05-13 19:44:56 +02007890 if (srv->admin & SRV_ADMF_MAINT) {
Willy Tarreaua0066dd2014-05-16 11:25:16 +02007891 newsrv->admin |= SRV_ADMF_IMAINT;
Willy Tarreau892337c2014-05-13 23:41:20 +02007892 newsrv->state = SRV_ST_STOPPED;
Simon Horman125d0992013-02-24 17:23:38 +09007893 newsrv->check.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007894 }
7895
7896 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01007897 newsrv->tracknext = srv->trackers;
7898 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007899
7900 free(newsrv->trackit);
7901 newsrv->trackit = NULL;
7902 }
7903 next_srv:
7904 newsrv = newsrv->next;
7905 }
7906
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007907 /* We have to initialize the server lookup mechanism depending
7908 * on what LB algorithm was choosen.
7909 */
7910
7911 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
7912 switch (curproxy->lbprm.algo & BE_LB_KIND) {
7913 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02007914 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
7915 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7916 init_server_map(curproxy);
7917 } else {
7918 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
7919 fwrr_init_server_groups(curproxy);
7920 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007921 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007922
Willy Tarreau3ebb1162012-02-13 16:57:44 +01007923 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01007924 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
7925 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
7926 fwlc_init_server_tree(curproxy);
7927 } else {
7928 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
7929 fas_init_server_tree(curproxy);
7930 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007931 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007932
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007933 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007934 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
7935 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
7936 chash_init_server_tree(curproxy);
7937 } else {
7938 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7939 init_server_map(curproxy);
7940 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007941 break;
7942 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007943
7944 if (curproxy->options & PR_O_LOGASAP)
7945 curproxy->to_log &= ~LW_BYTES;
7946
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007947 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01007948 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007949 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
7950 proxy_type_str(curproxy), curproxy->id);
7951 err_code |= ERR_WARN;
7952 }
7953
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007954 if (curproxy->mode != PR_MODE_HTTP) {
7955 int optnum;
7956
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007957 if (curproxy->uri_auth) {
7958 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
7959 proxy_type_str(curproxy), curproxy->id);
7960 err_code |= ERR_WARN;
7961 curproxy->uri_auth = NULL;
7962 }
7963
Willy Tarreau87cf5142011-08-19 22:57:24 +02007964 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007965 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7966 "forwardfor", proxy_type_str(curproxy), curproxy->id);
7967 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02007968 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007969 }
7970
7971 if (curproxy->options & PR_O_ORGTO) {
7972 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7973 "originalto", proxy_type_str(curproxy), curproxy->id);
7974 err_code |= ERR_WARN;
7975 curproxy->options &= ~PR_O_ORGTO;
7976 }
7977
7978 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
7979 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
7980 (curproxy->cap & cfg_opts[optnum].cap) &&
7981 (curproxy->options & cfg_opts[optnum].val)) {
7982 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7983 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
7984 err_code |= ERR_WARN;
7985 curproxy->options &= ~cfg_opts[optnum].val;
7986 }
7987 }
7988
7989 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
7990 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
7991 (curproxy->cap & cfg_opts2[optnum].cap) &&
7992 (curproxy->options2 & cfg_opts2[optnum].val)) {
7993 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7994 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
7995 err_code |= ERR_WARN;
7996 curproxy->options2 &= ~cfg_opts2[optnum].val;
7997 }
7998 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007999
Pieter Baauwd551fb52013-05-08 22:49:23 +02008000#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008001 if (curproxy->conn_src.bind_hdr_occ) {
8002 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008003 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01008004 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008005 err_code |= ERR_WARN;
8006 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008007#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008008 }
8009
Willy Tarreaubaaee002006-06-26 02:48:02 +02008010 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01008011 * ensure that we're not cross-dressing a TCP server into HTTP.
8012 */
8013 newsrv = curproxy->srv;
8014 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01008015 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008016 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
8017 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008018 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01008019 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008020
Willy Tarreau0cec3312011-10-31 13:49:26 +01008021 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
8022 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
8023 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8024 err_code |= ERR_WARN;
8025 }
8026
Willy Tarreauc93cd162014-05-13 15:54:22 +02008027 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02008028 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
8029 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8030 err_code |= ERR_WARN;
8031 }
8032
Pieter Baauwd551fb52013-05-08 22:49:23 +02008033#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008034 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
8035 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008036 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 +01008037 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008038 err_code |= ERR_WARN;
8039 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008040#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01008041 newsrv = newsrv->next;
8042 }
8043
Willy Tarreaue42bd962014-09-16 16:21:19 +02008044 /* check if we have a frontend with "tcp-request content" looking at L7
8045 * with no inspect-delay
8046 */
8047 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
8048 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
8049 if (trule->action == TCP_ACT_CAPTURE &&
8050 !(trule->act_prm.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
8051 break;
8052 if ((trule->action >= TCP_ACT_TRK_SC0 && trule->action <= TCP_ACT_TRK_SCMAX) &&
8053 !(trule->act_prm.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
8054 break;
8055 }
8056
8057 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
8058 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
8059 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
8060 " This means that these rules will randomly find their contents. This can be fixed by"
8061 " setting the tcp-request inspect-delay.\n",
8062 proxy_type_str(curproxy), curproxy->id);
8063 err_code |= ERR_WARN;
8064 }
8065 }
8066
Willy Tarreauc1a21672009-08-16 22:37:44 +02008067 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02008068 if (!curproxy->accept)
8069 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02008070
Willy Tarreauc1a21672009-08-16 22:37:44 +02008071 if (curproxy->tcp_req.inspect_delay ||
8072 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02008073 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008074
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008075 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008076 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008077 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008078 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008079
8080 /* both TCP and HTTP must check switching rules */
8081 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
8082 }
8083
8084 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02008085 if (curproxy->tcp_req.inspect_delay ||
8086 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
8087 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
8088
Emeric Brun97679e72010-09-23 17:56:44 +02008089 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
8090 curproxy->be_rsp_ana |= AN_RES_INSPECT;
8091
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008092 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008093 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008094 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008095 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008096
8097 /* If the backend does requires RDP cookie persistence, we have to
8098 * enable the corresponding analyser.
8099 */
8100 if (curproxy->options2 & PR_O2_RDPC_PRST)
8101 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
8102 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008103 }
8104
8105 /***********************************************************/
8106 /* At this point, target names have already been resolved. */
8107 /***********************************************************/
8108
8109 /* Check multi-process mode compatibility */
8110
8111 if (global.nbproc > 1 && global.stats_fe) {
8112 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8113 unsigned long mask;
8114
8115 mask = nbits(global.nbproc);
8116 if (global.stats_fe->bind_proc)
8117 mask &= global.stats_fe->bind_proc;
8118
8119 if (bind_conf->bind_proc)
8120 mask &= bind_conf->bind_proc;
8121
8122 /* stop here if more than one process is used */
8123 if (popcount(mask) > 1)
8124 break;
8125 }
8126 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
8127 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");
8128 }
8129 }
8130
8131 /* Make each frontend inherit bind-process from its listeners when not specified. */
8132 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8133 if (curproxy->bind_proc)
8134 continue;
8135
8136 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8137 unsigned long mask;
8138
Willy Tarreaue428b082015-05-04 21:57:58 +02008139 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008140 curproxy->bind_proc |= mask;
8141 }
8142
8143 if (!curproxy->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008144 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008145 }
8146
8147 if (global.stats_fe) {
8148 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8149 unsigned long mask;
8150
Willy Tarreaue428b082015-05-04 21:57:58 +02008151 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008152 global.stats_fe->bind_proc |= mask;
8153 }
8154 if (!global.stats_fe->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008155 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008156 }
8157
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02008158 /* propagate bindings from frontends to backends. Don't do it if there
8159 * are any fatal errors as we must not call it with unresolved proxies.
8160 */
8161 if (!cfgerr) {
8162 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8163 if (curproxy->cap & PR_CAP_FE)
8164 propagate_processes(curproxy, NULL);
8165 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008166 }
8167
8168 /* Bind each unbound backend to all processes when not specified. */
8169 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8170 if (curproxy->bind_proc)
8171 continue;
Willy Tarreaue428b082015-05-04 21:57:58 +02008172 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008173 }
8174
8175 /*******************************************************/
8176 /* At this step, all proxies have a non-null bind_proc */
8177 /*******************************************************/
8178
8179 /* perform the final checks before creating tasks */
8180
8181 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8182 struct listener *listener;
8183 unsigned int next_id;
8184 int nbproc;
8185
8186 nbproc = popcount(curproxy->bind_proc & nbits(global.nbproc));
Willy Tarreauc1a21672009-08-16 22:37:44 +02008187
Emeric Brunc52962f2012-11-15 18:28:02 +01008188#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008189 /* Configure SSL for each bind line.
8190 * Note: if configuration fails at some point, the ->ctx member
8191 * remains NULL so that listeners can later detach.
8192 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008193 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008194 int alloc_ctx;
8195
Emeric Brunc52962f2012-11-15 18:28:02 +01008196 if (!bind_conf->is_ssl) {
8197 if (bind_conf->default_ctx) {
8198 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
8199 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
8200 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008201 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01008202 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008203 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02008204 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008205 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008206 cfgerr++;
8207 continue;
8208 }
8209
Emeric Brun8dc60392014-05-09 13:52:00 +02008210 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008211 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02008212 if (alloc_ctx == SHCTX_E_INIT_LOCK)
8213 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");
8214 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008215 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02008216 cfgerr++;
8217 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008218 }
8219
Emeric Brunfc0421f2012-09-07 17:30:07 +02008220 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008221 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008222 }
Emeric Brunc52962f2012-11-15 18:28:02 +01008223#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008224
Willy Tarreaue6b98942007-10-29 01:09:36 +01008225 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008226 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008227 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008228 if (!listener->luid) {
8229 /* listener ID not set, use automatic numbering with first
8230 * spare entry starting with next_luid.
8231 */
8232 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
8233 listener->conf.id.key = listener->luid = next_id;
8234 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008235 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01008236 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008237
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008238 /* enable separate counters */
8239 if (curproxy->options2 & PR_O2_SOCKSTAT) {
8240 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01008241 if (!listener->name)
8242 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008243 }
Willy Tarreau81796be2012-09-22 19:11:47 +02008244
Willy Tarreaue6b98942007-10-29 01:09:36 +01008245 if (curproxy->options & PR_O_TCP_NOLING)
8246 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02008247 if (!listener->maxconn)
8248 listener->maxconn = curproxy->maxconn;
8249 if (!listener->backlog)
8250 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01008251 if (!listener->maxaccept)
8252 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
8253
8254 /* we want to have an optimal behaviour on single process mode to
8255 * maximize the work at once, but in multi-process we want to keep
8256 * some fairness between processes, so we target half of the max
8257 * number of events to be balanced over all the processes the proxy
8258 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
8259 * used to disable the limit.
8260 */
8261 if (listener->maxaccept > 0) {
8262 if (nbproc > 1)
8263 listener->maxaccept = (listener->maxaccept + 1) / 2;
8264 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
8265 }
8266
Willy Tarreau9903f0e2015-04-04 18:50:31 +02008267 listener->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02008268 listener->handler = process_stream;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008269 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01008270 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01008271
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008272 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
8273 listener->options |= LI_O_TCP_RULES;
8274
Willy Tarreaude3041d2010-05-31 10:56:17 +02008275 if (curproxy->mon_mask.s_addr)
8276 listener->options |= LI_O_CHK_MONNET;
8277
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008278 /* smart accept mode is automatic in HTTP mode */
8279 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008280 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008281 !(curproxy->no_options2 & PR_O2_SMARTACC)))
8282 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01008283 }
8284
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008285 /* Release unused SSL configs */
8286 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8287 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008288 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008289#ifdef USE_OPENSSL
8290 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008291 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008292 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02008293 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008294 free(bind_conf->crl_file);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008295 if(bind_conf->keys_ref) {
8296 free(bind_conf->keys_ref->filename);
8297 free(bind_conf->keys_ref->tlskeys);
8298 free(bind_conf->keys_ref);
8299 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008300#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008301 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008302
Willy Tarreau102df612014-05-07 23:56:38 +02008303 if (nbproc > 1) {
8304 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02008305 int count, maxproc = 0;
8306
8307 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8308 count = popcount(bind_conf->bind_proc);
8309 if (count > maxproc)
8310 maxproc = count;
8311 }
8312 /* backends have 0, frontends have 1 or more */
8313 if (maxproc != 1)
8314 Warning("Proxy '%s': in multi-process mode, stats will be"
8315 " limited to process assigned to the current request.\n",
8316 curproxy->id);
8317
Willy Tarreau102df612014-05-07 23:56:38 +02008318 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
8319 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
8320 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008321 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008322 }
Willy Tarreau102df612014-05-07 23:56:38 +02008323 if (curproxy->appsession_name) {
8324 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
8325 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008326 }
Willy Tarreau102df612014-05-07 23:56:38 +02008327 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
8328 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
8329 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008330 }
8331 }
Willy Tarreau918ff602011-07-25 16:33:49 +02008332
8333 /* create the task associated with the proxy */
8334 curproxy->task = task_new();
8335 if (curproxy->task) {
8336 curproxy->task->context = curproxy;
8337 curproxy->task->process = manage_proxy;
8338 /* no need to queue, it will be done automatically if some
8339 * listener gets limited.
8340 */
8341 curproxy->task->expire = TICK_ETERNITY;
8342 } else {
8343 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
8344 curproxy->id);
8345 cfgerr++;
8346 }
Willy Tarreaub369a042014-09-16 13:21:03 +02008347 }
8348
Willy Tarreaufbb78422011-06-05 15:38:35 +02008349 /* automatically compute fullconn if not set. We must not do it in the
8350 * loop above because cross-references are not yet fully resolved.
8351 */
8352 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8353 /* If <fullconn> is not set, let's set it to 10% of the sum of
8354 * the possible incoming frontend's maxconns.
8355 */
8356 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
8357 struct proxy *fe;
8358 int total = 0;
8359
8360 /* sum up the number of maxconns of frontends which
8361 * reference this backend at least once or which are
8362 * the same one ('listen').
8363 */
8364 for (fe = proxy; fe; fe = fe->next) {
8365 struct switching_rule *rule;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008366 int found = 0;
8367
8368 if (!(fe->cap & PR_CAP_FE))
8369 continue;
8370
8371 if (fe == curproxy) /* we're on a "listen" instance */
8372 found = 1;
8373
8374 if (fe->defbe.be == curproxy) /* "default_backend" */
8375 found = 1;
8376
8377 /* check if a "use_backend" rule matches */
8378 if (!found) {
8379 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01008380 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02008381 found = 1;
8382 break;
8383 }
8384 }
8385 }
8386
Willy Tarreaufbb78422011-06-05 15:38:35 +02008387 /* now we've checked all possible ways to reference a backend
8388 * from a frontend.
8389 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02008390 if (!found)
8391 continue;
8392 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008393 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02008394 /* we have the sum of the maxconns in <total>. We only
8395 * keep 10% of that sum to set the default fullconn, with
8396 * a hard minimum of 1 (to avoid a divide by zero).
8397 */
8398 curproxy->fullconn = (total + 9) / 10;
8399 if (!curproxy->fullconn)
8400 curproxy->fullconn = 1;
8401 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01008402 }
8403
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008404 /*
8405 * Recount currently required checks.
8406 */
8407
8408 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
8409 int optnum;
8410
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008411 for (optnum = 0; cfg_opts[optnum].name; optnum++)
8412 if (curproxy->options & cfg_opts[optnum].val)
8413 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008414
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008415 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
8416 if (curproxy->options2 & cfg_opts2[optnum].val)
8417 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008418 }
8419
Willy Tarreau0fca4832015-05-01 19:12:05 +02008420 /* compute the required process bindings for the peers */
8421 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
8422 if (curproxy->table.peers.p)
8423 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
8424
Willy Tarreau122541c2011-09-07 21:24:49 +02008425 if (peers) {
8426 struct peers *curpeers = peers, **last;
8427 struct peer *p, *pb;
8428
Willy Tarreau1e273012015-05-01 19:15:17 +02008429 /* Remove all peers sections which don't have a valid listener,
8430 * which are not used by any table, or which are bound to more
8431 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02008432 */
8433 last = &peers;
8434 while (*last) {
8435 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008436
8437 if (curpeers->state == PR_STSTOPPED) {
8438 /* the "disabled" keyword was present */
8439 if (curpeers->peers_fe)
8440 stop_proxy(curpeers->peers_fe);
8441 curpeers->peers_fe = NULL;
8442 }
8443 else if (!curpeers->peers_fe) {
8444 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
8445 curpeers->id, localpeer);
8446 }
Willy Tarreau1e273012015-05-01 19:15:17 +02008447 else if (popcount(curpeers->peers_fe->bind_proc) != 1) {
8448 /* either it's totally stopped or too much used */
8449 if (curpeers->peers_fe->bind_proc) {
8450 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreau64c57222015-05-04 21:48:51 +02008451 "running in different processes (%d different ones). "
8452 "Check global.nbproc and all tables' bind-process "
8453 "settings.\n", curpeers->id, popcount(curpeers->peers_fe->bind_proc));
Willy Tarreau1e273012015-05-01 19:15:17 +02008454 cfgerr++;
8455 }
8456 stop_proxy(curpeers->peers_fe);
8457 curpeers->peers_fe = NULL;
8458 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008459 else {
Emeric Brunb3971ab2015-05-12 18:49:09 +02008460 peers_init_sync(curpeers);
Willy Tarreau122541c2011-09-07 21:24:49 +02008461 last = &curpeers->next;
8462 continue;
8463 }
8464
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008465 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02008466 p = curpeers->remote;
8467 while (p) {
8468 pb = p->next;
8469 free(p->id);
8470 free(p);
8471 p = pb;
8472 }
8473
8474 /* Destroy and unlink this curpeers section.
8475 * Note: curpeers is backed up into *last.
8476 */
8477 free(curpeers->id);
8478 curpeers = curpeers->next;
8479 free(*last);
8480 *last = curpeers;
8481 }
8482 }
8483
Willy Tarreau6866f3f2015-05-01 19:09:08 +02008484 /* initialize stick-tables on backend capable proxies. This must not
8485 * be done earlier because the data size may be discovered while parsing
8486 * other proxies.
8487 */
8488 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8489 if (curproxy->state == PR_STSTOPPED)
8490 continue;
8491
8492 if (!stktable_init(&curproxy->table)) {
8493 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
8494 cfgerr++;
8495 }
8496 }
8497
Simon Horman0d16a402015-01-30 11:22:58 +09008498 if (mailers) {
8499 struct mailers *curmailers = mailers, **last;
8500 struct mailer *m, *mb;
8501
8502 /* Remove all mailers sections which don't have a valid listener.
8503 * This can happen when a mailers section is never referenced.
8504 */
8505 last = &mailers;
8506 while (*last) {
8507 curmailers = *last;
8508 if (curmailers->users) {
8509 last = &curmailers->next;
8510 continue;
8511 }
8512
8513 Warning("Removing incomplete section 'mailers %s'.\n",
8514 curmailers->id);
8515
8516 m = curmailers->mailer_list;
8517 while (m) {
8518 mb = m->next;
8519 free(m->id);
8520 free(m);
8521 m = mb;
8522 }
8523
8524 /* Destroy and unlink this curmailers section.
8525 * Note: curmailers is backed up into *last.
8526 */
8527 free(curmailers->id);
8528 curmailers = curmailers->next;
8529 free(*last);
8530 *last = curmailers;
8531 }
8532 }
8533
Willy Tarreau34eb6712011-10-24 18:15:04 +02008534 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02008535 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02008536 MEM_F_SHARED);
8537
Willy Tarreaubb925012009-07-23 13:36:36 +02008538 if (cfgerr > 0)
8539 err_code |= ERR_ALERT | ERR_FATAL;
8540 out:
8541 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02008542}
8543
Willy Tarreau5b2c3362008-07-09 19:39:06 +02008544/*
8545 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
8546 * parsing sessions.
8547 */
8548void cfg_register_keywords(struct cfg_kw_list *kwl)
8549{
8550 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
8551}
Willy Tarreaubaaee002006-06-26 02:48:02 +02008552
Willy Tarreau5b2c3362008-07-09 19:39:06 +02008553/*
8554 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
8555 */
8556void cfg_unregister_keywords(struct cfg_kw_list *kwl)
8557{
8558 LIST_DEL(&kwl->list);
8559 LIST_INIT(&kwl->list);
8560}
Willy Tarreaubaaee002006-06-26 02:48:02 +02008561
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01008562/* this function register new section in the haproxy configuration file.
8563 * <section_name> is the name of this new section and <section_parser>
8564 * is the called parser. If two section declaration have the same name,
8565 * only the first declared is used.
8566 */
8567int cfg_register_section(char *section_name,
8568 int (*section_parser)(const char *, int, char **, int))
8569{
8570 struct cfg_section *cs;
8571
8572 cs = calloc(1, sizeof(*cs));
8573 if (!cs) {
8574 Alert("register section '%s': out of memory.\n", section_name);
8575 return 0;
8576 }
8577
8578 cs->section_name = section_name;
8579 cs->section_parser = section_parser;
8580
8581 LIST_ADDQ(&sections, &cs->list);
8582
8583 return 1;
8584}
8585
Willy Tarreaubaaee002006-06-26 02:48:02 +02008586/*
8587 * Local variables:
8588 * c-indent-level: 8
8589 * c-basic-offset: 8
8590 * End:
8591 */